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 dalvik.annotation.optimization.FastNative; 20import java.lang.ref.FinalizerReference; 21import java.util.HashMap; 22import java.util.Map; 23import 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 */ 32public 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 */ 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 */ 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 */ 87 public native String[] properties(); 88 89 /** 90 * Returns the VM's boot class path. 91 */ 92 public native String bootClassPath(); 93 94 /** 95 * Returns the VM's class path. 96 */ 97 public native String classPath(); 98 99 /** 100 * Returns the VM's version. 101 */ 102 public native String vmVersion(); 103 104 /** 105 * Returns the name of the shared library providing the VM implementation. 106 */ 107 public native String vmLibrary(); 108 109 /** 110 * Returns the VM's instruction set. 111 */ 112 public native String vmInstructionSet(); 113 114 /** 115 * Returns whether the VM is running in 64-bit mode. 116 */ 117 @FastNative 118 public native boolean is64Bit(); 119 120 /** 121 * Returns whether the VM is running with JNI checking enabled. 122 */ 123 @FastNative 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 */ 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 <= 0.0 or >= 1.0 148 */ 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 */ 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 */ 179 public synchronized int getTargetSdkVersion() { 180 return targetSdkVersion; 181 } 182 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 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 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 208 public void gcSoftReferences() {} 209 210 /** 211 * This method exists for binary compatibility. It is equivalent 212 * to {@link System#runFinalization}. 213 */ 214 @Deprecated 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 */ 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 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 */ 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 */ 321 public native void clampGrowthLimit(); 322 323 /** 324 * Returns true if either a Java debugger or native debugger is active. 325 */ 326 @FastNative 327 public native boolean isDebuggerActive(); 328 329 /** 330 * Returns true if native debugging is on. 331 */ 332 @FastNative 333 public native boolean isNativeDebuggable(); 334 335 /** 336 * Returns true if Java debugging is enabled. 337 */ 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 */ 348 public native void registerNativeAllocation(int bytes); 349 350 /** 351 * Registers a native free by reducing the number of native bytes accounted for. 352 */ 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 */ 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 379 public native void requestConcurrentGC(); 380 public native void concurrentGC(); 381 public native void requestHeapTrim(); 382 public native void trimHeap(); 383 public native void startHeapTaskProcessor(); 384 public native void stopHeapTaskProcessor(); 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 */ 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 */ 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 */ 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 */ 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 422 public static boolean is64BitInstructionSet(String instructionSet) { 423 return "arm64".equals(instructionSet) || 424 "x86_64".equals(instructionSet) || 425 "mips64".equals(instructionSet); 426 } 427 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 */ 437 public static native boolean isBootClassPathOnDisk(String instructionSet); 438 439 /** 440 * Returns the instruction set of the current runtime. 441 */ 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 */ 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 */ 455 public static native void registerSensitiveThread(); 456 457 /** 458 * Sets up the priority of the system daemon thread (caller). 459 */ 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 */ 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 */ 474 public static native void setDedupeHiddenApiWarnings(boolean dedupe); 475 476 /** 477 * Sets the package name of the app running in this process. 478 */ 479 public static native void setProcessPackageName(String packageName); 480} 481