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 <= 0.0 or >= 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