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