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