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
17package dalvik.system;
18
19import java.lang.ref.FinalizerReference;
20import java.util.HashMap;
21import 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 */
30public 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     */
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     */
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     */
75    public native String[] properties();
76
77    /**
78     * Returns the VM's boot class path.
79     */
80    public native String bootClassPath();
81
82    /**
83     * Returns the VM's class path.
84     */
85    public native String classPath();
86
87    /**
88     * Returns the VM's version.
89     */
90    public native String vmVersion();
91
92    /**
93     * Returns the name of the shared library providing the VM implementation.
94     */
95    public native String vmLibrary();
96
97    /**
98     * Returns the VM's instruction set.
99     */
100    public native String vmInstructionSet();
101
102    /**
103     * Returns whether the VM is running in 64-bit mode.
104     */
105    public native boolean is64Bit();
106
107    /**
108     * Returns whether the VM is running with JNI checking enabled.
109     */
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     */
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     */
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     */
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     */
168    public synchronized int getTargetSdkVersion() {
169        return targetSdkVersion;
170    }
171
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
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
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
197    public void gcSoftReferences() {}
198
199    /**
200     * This method exists for binary compatibility.  It is equivalent
201     * to {@link System#runFinalization}.
202     */
203    @Deprecated
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     */
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
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
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
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     */
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     */
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     */
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     */
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     */
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     */
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     */
283    public native void clampGrowthLimit();
284
285    /**
286     * Returns true if either a Java debugger or native debugger is active.
287     */
288    public native boolean isDebuggerActive();
289
290    /**
291     * Returns true if native debugging is on.
292     */
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     */
303    public native void registerNativeAllocation(int bytes);
304
305    /**
306     * Registers a native free by reducing the number of native bytes accounted for.
307     */
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     */
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
334    public native void requestConcurrentGC();
335    public native void concurrentGC();
336    public native void requestHeapTrim();
337    public native void trimHeap();
338    public native void startHeapTaskProcessor();
339    public native void stopHeapTaskProcessor();
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     */
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     */
352    public native void preloadDexCaches();
353
354    /**
355     * Register application info
356     */
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     */
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
376    public static boolean is64BitInstructionSet(String instructionSet) {
377        return "arm64".equals(instructionSet) ||
378                "x86_64".equals(instructionSet) ||
379                "mips64".equals(instructionSet);
380    }
381
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     */
391    public static native boolean isBootClassPathOnDisk(String instructionSet);
392
393    /**
394     * Returns the instruction set of the current runtime.
395     */
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     */
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     */
409    public static native void registerSensitiveThread();
410}
411