1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package dalvik.system;
18 
19 import java.lang.ref.FinalizerReference;
20 import java.util.HashMap;
21 import java.util.Map;
22 
23 /**
24  * Provides an interface to VM-global, Dalvik-specific features.
25  * An application cannot create its own Runtime instance, and must obtain
26  * one from the getRuntime method.
27  *
28  * @hide
29  */
30 public final class VMRuntime {
31 
32     /**
33      * Holds the VMRuntime singleton.
34      */
35     private static final VMRuntime THE_ONE = new VMRuntime();
36 
37     // Note: Instruction set names are used to construct the names of some
38     // system properties. To be sure that the properties stay valid the
39     // instruction set name should not exceed 7 characters. See installd
40     // and the package manager for the actual propeties.
41     private static final Map<String, String> ABI_TO_INSTRUCTION_SET_MAP
42             = new HashMap<String, String>(16);
43     static {
44         ABI_TO_INSTRUCTION_SET_MAP.put("armeabi", "arm");
45         ABI_TO_INSTRUCTION_SET_MAP.put("armeabi-v7a", "arm");
46         ABI_TO_INSTRUCTION_SET_MAP.put("mips", "mips");
47         ABI_TO_INSTRUCTION_SET_MAP.put("mips64", "mips64");
48         ABI_TO_INSTRUCTION_SET_MAP.put("x86", "x86");
49         ABI_TO_INSTRUCTION_SET_MAP.put("x86_64", "x86_64");
50         ABI_TO_INSTRUCTION_SET_MAP.put("arm64-v8a", "arm64");
51     }
52 
53     private int targetSdkVersion;
54 
55     /**
56      * Prevents this class from being instantiated.
57      */
VMRuntime()58     private VMRuntime() {
59     }
60 
61     /**
62      * Returns the object that represents the VM instance's Dalvik-specific
63      * runtime environment.
64      *
65      * @return the runtime object
66      */
getRuntime()67     public static VMRuntime getRuntime() {
68         return THE_ONE;
69     }
70 
71     /**
72      * Returns a copy of the VM's command-line property settings.
73      * These are in the form "name=value" rather than "-Dname=value".
74      */
properties()75     public native String[] properties();
76 
77     /**
78      * Returns the VM's boot class path.
79      */
bootClassPath()80     public native String bootClassPath();
81 
82     /**
83      * Returns the VM's class path.
84      */
classPath()85     public native String classPath();
86 
87     /**
88      * Returns the VM's version.
89      */
vmVersion()90     public native String vmVersion();
91 
92     /**
93      * Returns the name of the shared library providing the VM implementation.
94      */
vmLibrary()95     public native String vmLibrary();
96 
97     /**
98      * Returns the VM's instruction set.
99      */
vmInstructionSet()100     public native String vmInstructionSet();
101 
102     /**
103      * Returns whether the VM is running in 64-bit mode.
104      */
is64Bit()105     public native boolean is64Bit();
106 
107     /**
108      * Returns whether the VM is running with JNI checking enabled.
109      */
isCheckJniEnabled()110     public native boolean isCheckJniEnabled();
111 
112     /**
113      * Gets the current ideal heap utilization, represented as a number
114      * between zero and one.  After a GC happens, the Dalvik heap may
115      * be resized so that (size of live objects) / (size of heap) is
116      * equal to this number.
117      *
118      * @return the current ideal heap utilization
119      */
getTargetHeapUtilization()120     public native float getTargetHeapUtilization();
121 
122     /**
123      * Sets the current ideal heap utilization, represented as a number
124      * between zero and one.  After a GC happens, the Dalvik heap may
125      * be resized so that (size of live objects) / (size of heap) is
126      * equal to this number.
127      *
128      * <p>This is only a hint to the garbage collector and may be ignored.
129      *
130      * @param newTarget the new suggested ideal heap utilization.
131      *                  This value may be adjusted internally.
132      * @return the previous ideal heap utilization
133      * @throws IllegalArgumentException if newTarget is &lt;= 0.0 or &gt;= 1.0
134      */
setTargetHeapUtilization(float newTarget)135     public float setTargetHeapUtilization(float newTarget) {
136         if (newTarget <= 0.0f || newTarget >= 1.0f) {
137             throw new IllegalArgumentException(newTarget +
138                     " out of range (0,1)");
139         }
140         /* Synchronize to make sure that only one thread gets
141          * a given "old" value if both update at the same time.
142          * Allows for reliable save-and-restore semantics.
143          */
144         synchronized (this) {
145             float oldTarget = getTargetHeapUtilization();
146             nativeSetTargetHeapUtilization(newTarget);
147             return oldTarget;
148         }
149     }
150 
151     /**
152      * Sets the target SDK version. Should only be called before the
153      * app starts to run, because it may change the VM's behavior in
154      * dangerous ways. Use 0 to mean "current" (since callers won't
155      * necessarily know the actual current SDK version, and the
156      * allocated version numbers start at 1), and 10000 to mean
157      * CUR_DEVELOPMENT.
158      */
setTargetSdkVersion(int targetSdkVersion)159     public synchronized void setTargetSdkVersion(int targetSdkVersion) {
160         this.targetSdkVersion = targetSdkVersion;
161         setTargetSdkVersionNative(this.targetSdkVersion);
162     }
163 
164     /**
165      * Gets the target SDK version. See {@link #setTargetSdkVersion} for
166      * special values.
167      */
getTargetSdkVersion()168     public synchronized int getTargetSdkVersion() {
169         return targetSdkVersion;
170     }
171 
setTargetSdkVersionNative(int targetSdkVersion)172     private native void setTargetSdkVersionNative(int targetSdkVersion);
173 
174     /**
175      * This method exists for binary compatibility.  It was part of a
176      * heap sizing API which was removed in Android 3.0 (Honeycomb).
177      */
178     @Deprecated
getMinimumHeapSize()179     public long getMinimumHeapSize() {
180         return 0;
181     }
182 
183     /**
184      * This method exists for binary compatibility.  It was part of a
185      * heap sizing API which was removed in Android 3.0 (Honeycomb).
186      */
187     @Deprecated
setMinimumHeapSize(long size)188     public long setMinimumHeapSize(long size) {
189         return 0;
190     }
191 
192     /**
193      * This method exists for binary compatibility.  It used to
194      * perform a garbage collection that cleared SoftReferences.
195      */
196     @Deprecated
gcSoftReferences()197     public void gcSoftReferences() {}
198 
199     /**
200      * This method exists for binary compatibility.  It is equivalent
201      * to {@link System#runFinalization}.
202      */
203     @Deprecated
runFinalizationSync()204     public void runFinalizationSync() {
205         System.runFinalization();
206     }
207 
208     /**
209      * Implements setTargetHeapUtilization().
210      *
211      * @param newTarget the new suggested ideal heap utilization.
212      *                  This value may be adjusted internally.
213      */
nativeSetTargetHeapUtilization(float newTarget)214     private native void nativeSetTargetHeapUtilization(float newTarget);
215 
216     /**
217      * This method exists for binary compatibility.  It was part of
218      * the external allocation API which was removed in Android 3.0 (Honeycomb).
219      */
220     @Deprecated
trackExternalAllocation(long size)221     public boolean trackExternalAllocation(long size) {
222         return true;
223     }
224 
225     /**
226      * This method exists for binary compatibility.  It was part of
227      * the external allocation API which was removed in Android 3.0 (Honeycomb).
228      */
229     @Deprecated
trackExternalFree(long size)230     public void trackExternalFree(long size) {}
231 
232     /**
233      * This method exists for binary compatibility.  It was part of
234      * the external allocation API which was removed in Android 3.0 (Honeycomb).
235      */
236     @Deprecated
getExternalBytesAllocated()237     public long getExternalBytesAllocated() {
238         return 0;
239     }
240 
241     /**
242      * Tells the VM to enable the JIT compiler. If the VM does not have a JIT
243      * implementation, calling this method should have no effect.
244      */
startJitCompilation()245     public native void startJitCompilation();
246 
247     /**
248      * Tells the VM to disable the JIT compiler. If the VM does not have a JIT
249      * implementation, calling this method should have no effect.
250      */
disableJitCompilation()251     public native void disableJitCompilation();
252 
253     /**
254      * Returns an array allocated in an area of the Java heap where it will never be moved.
255      * This is used to implement native allocations on the Java heap, such as DirectByteBuffers
256      * and Bitmaps.
257      */
newNonMovableArray(Class<?> componentType, int length)258     public native Object newNonMovableArray(Class<?> componentType, int length);
259 
260     /**
261      * Returns an array of at least minLength, but potentially larger. The increased size comes from
262      * avoiding any padding after the array. The amount of padding varies depending on the
263      * componentType and the memory allocator implementation.
264      */
newUnpaddedArray(Class<?> componentType, int minLength)265     public native Object newUnpaddedArray(Class<?> componentType, int minLength);
266 
267     /**
268      * Returns the address of array[0]. This differs from using JNI in that JNI might lie and
269      * give you the address of a copy of the array when in forcecopy mode.
270      */
addressOf(Object array)271     public native long addressOf(Object array);
272 
273     /**
274      * Removes any growth limits, allowing the application to allocate
275      * up to the maximum heap size.
276      */
clearGrowthLimit()277     public native void clearGrowthLimit();
278 
279     /**
280      * Make the current growth limit the new non growth limit capacity by releasing pages which
281      * are after the growth limit but before the non growth limit capacity.
282      */
clampGrowthLimit()283     public native void clampGrowthLimit();
284 
285     /**
286      * Returns true if either a Java debugger or native debugger is active.
287      */
isDebuggerActive()288     public native boolean isDebuggerActive();
289 
290     /**
291      * Returns true if native debugging is on.
292      */
isNativeDebuggable()293     public native boolean isNativeDebuggable();
294 
295     /**
296      * Registers a native allocation so that the heap knows about it and performs GC as required.
297      * If the number of native allocated bytes exceeds the native allocation watermark, the
298      * function requests a concurrent GC. If the native bytes allocated exceeds a second higher
299      * watermark, it is determined that the application is registering native allocations at an
300      * unusually high rate and a GC is performed inside of the function to prevent memory usage
301      * from excessively increasing.
302      */
registerNativeAllocation(int bytes)303     public native void registerNativeAllocation(int bytes);
304 
305     /**
306      * Registers a native free by reducing the number of native bytes accounted for.
307      */
registerNativeFree(int bytes)308     public native void registerNativeFree(int bytes);
309 
310     /**
311      * Wait for objects to be finalized.
312      *
313      * If finalization takes longer than timeout, then the function returns before all objects are
314      * finalized.
315      *
316      * @param timeout
317      *            timeout in nanoseconds of the maximum time to wait until all pending finalizers
318      *            are run. If timeout is 0, then there is no timeout. Note that the timeout does
319      *            not stop the finalization process, it merely stops the wait.
320      *
321      * @see #Runtime.runFinalization()
322      * @see #wait(long,int)
323      */
runFinalization(long timeout)324     public static void runFinalization(long timeout) {
325         try {
326             FinalizerReference.finalizeAllEnqueued(timeout);
327         } catch (InterruptedException e) {
328             // Interrupt the current thread without actually throwing the InterruptionException
329             // for the caller.
330             Thread.currentThread().interrupt();
331         }
332     }
333 
requestConcurrentGC()334     public native void requestConcurrentGC();
concurrentGC()335     public native void concurrentGC();
requestHeapTrim()336     public native void requestHeapTrim();
trimHeap()337     public native void trimHeap();
startHeapTaskProcessor()338     public native void startHeapTaskProcessor();
stopHeapTaskProcessor()339     public native void stopHeapTaskProcessor();
runHeapTasks()340     public native void runHeapTasks();
341 
342     /**
343      * Let the heap know of the new process state. This can change allocation and garbage collection
344      * behavior regarding trimming and compaction.
345      */
updateProcessState(int state)346     public native void updateProcessState(int state);
347 
348     /**
349      * Fill in dex caches with classes, fields, and methods that are
350      * already loaded. Typically used after Zygote preloading.
351      */
preloadDexCaches()352     public native void preloadDexCaches();
353 
354     /**
355      * Register application info
356      */
registerAppInfo(String packageName, String appDir, String[] codePaths, String foreignDexProfileDir)357     public static native void registerAppInfo(String packageName, String appDir,
358              String[] codePaths, String foreignDexProfileDir);
359 
360     /**
361      * Returns the runtime instruction set corresponding to a given ABI. Multiple
362      * compatible ABIs might map to the same instruction set. For example
363      * {@code armeabi-v7a} and {@code armeabi} might map to the instruction set {@code arm}.
364      *
365      * This influences the compilation of the applications classes.
366      */
getInstructionSet(String abi)367     public static String getInstructionSet(String abi) {
368         final String instructionSet = ABI_TO_INSTRUCTION_SET_MAP.get(abi);
369         if (instructionSet == null) {
370             throw new IllegalArgumentException("Unsupported ABI: " + abi);
371         }
372 
373         return instructionSet;
374     }
375 
is64BitInstructionSet(String instructionSet)376     public static boolean is64BitInstructionSet(String instructionSet) {
377         return "arm64".equals(instructionSet) ||
378                 "x86_64".equals(instructionSet) ||
379                 "mips64".equals(instructionSet);
380     }
381 
is64BitAbi(String abi)382     public static boolean is64BitAbi(String abi) {
383         return is64BitInstructionSet(getInstructionSet(abi));
384     }
385 
386     /**
387      * Return false if the boot class path for the given instruction
388      * set mapped from disk storage, versus being interpretted from
389      * dirty pages in memory.
390      */
isBootClassPathOnDisk(String instructionSet)391     public static native boolean isBootClassPathOnDisk(String instructionSet);
392 
393     /**
394      * Returns the instruction set of the current runtime.
395      */
getCurrentInstructionSet()396     public static native String getCurrentInstructionSet();
397 
398     /**
399      * Return true if the dalvik cache was pruned when booting. This may have happened for
400      * various reasons, e.g., after an OTA. The return value is for the current instruction
401      * set.
402      */
didPruneDalvikCache()403     public static native boolean didPruneDalvikCache();
404 
405     /**
406      * Register the current execution thread to the runtime as sensitive thread.
407      * Should be called just once. Subsequent calls are ignored.
408      */
registerSensitiveThread()409     public static native void registerSensitiveThread();
410 }
411