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.util.HashMap;
20 import java.util.Map;
21 
22 /**
23  * Provides an interface to VM-global, Dalvik-specific features.
24  * An application cannot create its own Runtime instance, and must obtain
25  * one from the getRuntime method.
26  *
27  * @hide
28  */
29 public final class VMRuntime {
30 
31     /**
32      * Holds the VMRuntime singleton.
33      */
34     private static final VMRuntime THE_ONE = new VMRuntime();
35 
36     private static final Map<String, String> ABI_TO_INSTRUCTION_SET_MAP
37             = new HashMap<String, String>();
38     static {
39         ABI_TO_INSTRUCTION_SET_MAP.put("armeabi", "arm");
40         ABI_TO_INSTRUCTION_SET_MAP.put("armeabi-v7a", "arm");
41         ABI_TO_INSTRUCTION_SET_MAP.put("mips", "mips");
42         ABI_TO_INSTRUCTION_SET_MAP.put("mips64", "mips64");
43         ABI_TO_INSTRUCTION_SET_MAP.put("x86", "x86");
44         ABI_TO_INSTRUCTION_SET_MAP.put("x86_64", "x86_64");
45         ABI_TO_INSTRUCTION_SET_MAP.put("arm64-v8a", "arm64");
46     }
47 
48     private int targetSdkVersion;
49 
50     /**
51      * Prevents this class from being instantiated.
52      */
VMRuntime()53     private VMRuntime() {
54     }
55 
56     /**
57      * Returns the object that represents the VM instance's Dalvik-specific
58      * runtime environment.
59      *
60      * @return the runtime object
61      */
getRuntime()62     public static VMRuntime getRuntime() {
63         return THE_ONE;
64     }
65 
66     /**
67      * Returns a copy of the VM's command-line property settings.
68      * These are in the form "name=value" rather than "-Dname=value".
69      */
properties()70     public native String[] properties();
71 
72     /**
73      * Returns the VM's boot class path.
74      */
bootClassPath()75     public native String bootClassPath();
76 
77     /**
78      * Returns the VM's class path.
79      */
classPath()80     public native String classPath();
81 
82     /**
83      * Returns the VM's version.
84      */
vmVersion()85     public native String vmVersion();
86 
87     /**
88      * Returns the name of the shared library providing the VM implementation.
89      */
vmLibrary()90     public native String vmLibrary();
91 
92     /**
93      * Returns the VM's instruction set.
94      */
vmInstructionSet()95     public native String vmInstructionSet();
96 
97     /**
98      * Returns whether the VM is running in 64-bit mode.
99      */
is64Bit()100     public native boolean is64Bit();
101 
102     /**
103      * Returns whether the VM is running with JNI checking enabled.
104      */
isCheckJniEnabled()105     public native boolean isCheckJniEnabled();
106 
107     /**
108      * Gets the current ideal heap utilization, represented as a number
109      * between zero and one.  After a GC happens, the Dalvik heap may
110      * be resized so that (size of live objects) / (size of heap) is
111      * equal to this number.
112      *
113      * @return the current ideal heap utilization
114      */
getTargetHeapUtilization()115     public native float getTargetHeapUtilization();
116 
117     /**
118      * Sets the current ideal heap utilization, represented as a number
119      * between zero and one.  After a GC happens, the Dalvik heap may
120      * be resized so that (size of live objects) / (size of heap) is
121      * equal to this number.
122      *
123      * <p>This is only a hint to the garbage collector and may be ignored.
124      *
125      * @param newTarget the new suggested ideal heap utilization.
126      *                  This value may be adjusted internally.
127      * @return the previous ideal heap utilization
128      * @throws IllegalArgumentException if newTarget is &lt;= 0.0 or &gt;= 1.0
129      */
setTargetHeapUtilization(float newTarget)130     public float setTargetHeapUtilization(float newTarget) {
131         if (newTarget <= 0.0f || newTarget >= 1.0f) {
132             throw new IllegalArgumentException(newTarget +
133                     " out of range (0,1)");
134         }
135         /* Synchronize to make sure that only one thread gets
136          * a given "old" value if both update at the same time.
137          * Allows for reliable save-and-restore semantics.
138          */
139         synchronized (this) {
140             float oldTarget = getTargetHeapUtilization();
141             nativeSetTargetHeapUtilization(newTarget);
142             return oldTarget;
143         }
144     }
145 
146     /**
147      * Sets the target SDK version. Should only be called before the
148      * app starts to run, because it may change the VM's behavior in
149      * dangerous ways. Use 0 to mean "current" (since callers won't
150      * necessarily know the actual current SDK version, and the
151      * allocated version numbers start at 1), and 10000 to mean
152      * CUR_DEVELOPMENT.
153      */
setTargetSdkVersion(int targetSdkVersion)154     public synchronized void setTargetSdkVersion(int targetSdkVersion) {
155         this.targetSdkVersion = targetSdkVersion;
156         setTargetSdkVersionNative(this.targetSdkVersion);
157     }
158 
159     /**
160      * Gets the target SDK version. See {@link #setTargetSdkVersion} for
161      * special values.
162      */
getTargetSdkVersion()163     public synchronized int getTargetSdkVersion() {
164         return targetSdkVersion;
165     }
166 
setTargetSdkVersionNative(int targetSdkVersion)167     private native void setTargetSdkVersionNative(int targetSdkVersion);
168 
169     /**
170      * This method exists for binary compatibility.  It was part of a
171      * heap sizing API which was removed in Android 3.0 (Honeycomb).
172      */
173     @Deprecated
getMinimumHeapSize()174     public long getMinimumHeapSize() {
175         return 0;
176     }
177 
178     /**
179      * This method exists for binary compatibility.  It was part of a
180      * heap sizing API which was removed in Android 3.0 (Honeycomb).
181      */
182     @Deprecated
setMinimumHeapSize(long size)183     public long setMinimumHeapSize(long size) {
184         return 0;
185     }
186 
187     /**
188      * This method exists for binary compatibility.  It used to
189      * perform a garbage collection that cleared SoftReferences.
190      */
191     @Deprecated
gcSoftReferences()192     public void gcSoftReferences() {}
193 
194     /**
195      * This method exists for binary compatibility.  It is equivalent
196      * to {@link System#runFinalization}.
197      */
198     @Deprecated
runFinalizationSync()199     public void runFinalizationSync() {
200         System.runFinalization();
201     }
202 
203     /**
204      * Implements setTargetHeapUtilization().
205      *
206      * @param newTarget the new suggested ideal heap utilization.
207      *                  This value may be adjusted internally.
208      */
nativeSetTargetHeapUtilization(float newTarget)209     private native void nativeSetTargetHeapUtilization(float newTarget);
210 
211     /**
212      * This method exists for binary compatibility.  It was part of
213      * the external allocation API which was removed in Android 3.0 (Honeycomb).
214      */
215     @Deprecated
trackExternalAllocation(long size)216     public boolean trackExternalAllocation(long size) {
217         return true;
218     }
219 
220     /**
221      * This method exists for binary compatibility.  It was part of
222      * the external allocation API which was removed in Android 3.0 (Honeycomb).
223      */
224     @Deprecated
trackExternalFree(long size)225     public void trackExternalFree(long size) {}
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
getExternalBytesAllocated()232     public long getExternalBytesAllocated() {
233         return 0;
234     }
235 
236     /**
237      * Tells the VM to enable the JIT compiler. If the VM does not have a JIT
238      * implementation, calling this method should have no effect.
239      */
startJitCompilation()240     public native void startJitCompilation();
241 
242     /**
243      * Tells the VM to disable the JIT compiler. If the VM does not have a JIT
244      * implementation, calling this method should have no effect.
245      */
disableJitCompilation()246     public native void disableJitCompilation();
247 
248     /**
249      * Returns an array allocated in an area of the Java heap where it will never be moved.
250      * This is used to implement native allocations on the Java heap, such as DirectByteBuffers
251      * and Bitmaps.
252      */
newNonMovableArray(Class<?> componentType, int length)253     public native Object newNonMovableArray(Class<?> componentType, int length);
254 
255     /**
256      * Returns an array of at least minLength, but potentially larger. The increased size comes from
257      * avoiding any padding after the array. The amount of padding varies depending on the
258      * componentType and the memory allocator implementation.
259      */
newUnpaddedArray(Class<?> componentType, int minLength)260     public native Object newUnpaddedArray(Class<?> componentType, int minLength);
261 
262     /**
263      * Returns the address of array[0]. This differs from using JNI in that JNI might lie and
264      * give you the address of a copy of the array when in forcecopy mode.
265      */
addressOf(Object array)266     public native long addressOf(Object array);
267 
268     /**
269      * Removes any growth limits, allowing the application to allocate
270      * up to the maximum heap size.
271      */
clearGrowthLimit()272     public native void clearGrowthLimit();
273 
274     /**
275      * Returns true if either a Java debugger or native debugger is active.
276      */
isDebuggerActive()277     public native boolean isDebuggerActive();
278 
279     /**
280      * Registers a native allocation so that the heap knows about it and performs GC as required.
281      * If the number of native allocated bytes exceeds the native allocation watermark, the
282      * function requests a concurrent GC. If the native bytes allocated exceeds a second higher
283      * watermark, it is determined that the application is registering native allocations at an
284      * unusually high rate and a GC is performed inside of the function to prevent memory usage
285      * from excessively increasing.
286      */
registerNativeAllocation(int bytes)287     public native void registerNativeAllocation(int bytes);
288 
289     /**
290      * Registers a native free by reducing the number of native bytes accounted for.
291      */
registerNativeFree(int bytes)292     public native void registerNativeFree(int bytes);
293 
trimHeap()294     public native void trimHeap();
concurrentGC()295     public native void concurrentGC();
296 
297     /**
298      * Let the heap know of the new process state. This can change allocation and garbage collection
299      * behavior regarding trimming and compaction.
300      */
updateProcessState(int state)301     public native void updateProcessState(int state);
302 
303     /**
304      * Fill in dex caches with classes, fields, and methods that are
305      * already loaded. Typically used after Zygote preloading.
306      */
preloadDexCaches()307     public native void preloadDexCaches();
308 
309     /**
310      * Register application info
311      */
registerAppInfo(String appDir, String processName, String pkgname)312     public static native void registerAppInfo(String appDir, String processName, String pkgname);
313 
314     /**
315      * Returns the runtime instruction set corresponding to a given ABI. Multiple
316      * compatible ABIs might map to the same instruction set. For example
317      * {@code armeabi-v7a} and {@code armeabi} might map to the instruction set {@code arm}.
318      *
319      * This influences the compilation of the applications classes.
320      */
getInstructionSet(String abi)321     public static String getInstructionSet(String abi) {
322         final String instructionSet = ABI_TO_INSTRUCTION_SET_MAP.get(abi);
323         if (instructionSet == null) {
324             throw new IllegalArgumentException("Unsupported ABI: " + abi);
325         }
326 
327         return instructionSet;
328     }
329 
is64BitInstructionSet(String instructionSet)330     public static boolean is64BitInstructionSet(String instructionSet) {
331         return "arm64".equals(instructionSet) ||
332                 "x86_64".equals(instructionSet) ||
333                 "mips64".equals(instructionSet);
334     }
335 
is64BitAbi(String abi)336     public static boolean is64BitAbi(String abi) {
337         return is64BitInstructionSet(getInstructionSet(abi));
338     }
339 
340     /**
341      * Return false if the boot class path for the given instruction
342      * set mapped from disk storage, versus being interpretted from
343      * dirty pages in memory.
344      */
isBootClassPathOnDisk(String instructionSet)345     public static native boolean isBootClassPathOnDisk(String instructionSet);
346 
347     /**
348      * Returns the instruction set of the current runtime.
349      */
getCurrentInstructionSet()350     public static native String getCurrentInstructionSet();
351 
352 }
353