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