1 /* 2 * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.internal.misc; 27 28 import static java.lang.Thread.State.*; 29 30 import dalvik.annotation.optimization.CriticalNative; 31 import java.util.Properties; 32 import java.util.HashMap; 33 import java.util.Map; 34 import java.util.Set; 35 36 public class VM { 37 38 /* The following methods used to be native methods that instruct 39 * the VM to selectively suspend certain threads in low-memory 40 * situations. They are inherently dangerous and not implementable 41 * on native threads. We removed them in JDK 1.2. The skeletons 42 * remain so that existing applications that use these methods 43 * will still work. 44 */ 45 private static boolean suspended = false; 46 47 /** @deprecated */ 48 @Deprecated threadsSuspended()49 public static boolean threadsSuspended() { 50 return suspended; 51 } 52 53 @SuppressWarnings("deprecation") allowThreadSuspension(ThreadGroup g, boolean b)54 public static boolean allowThreadSuspension(ThreadGroup g, boolean b) { 55 return g.allowThreadSuspension(b); 56 } 57 58 /** @deprecated */ 59 @Deprecated suspendThreads()60 public static boolean suspendThreads() { 61 suspended = true; 62 return true; 63 } 64 65 // Causes any suspended threadgroups to be resumed. 66 /** @deprecated */ 67 @Deprecated unsuspendThreads()68 public static void unsuspendThreads() { 69 suspended = false; 70 } 71 72 // Causes threadgroups no longer marked suspendable to be resumed. 73 /** @deprecated */ 74 @Deprecated unsuspendSomeThreads()75 public static void unsuspendSomeThreads() { 76 } 77 78 /* Deprecated fields and methods -- Memory advice not supported in 1.2 */ 79 80 /** @deprecated */ 81 @Deprecated 82 public static final int STATE_GREEN = 1; 83 84 /** @deprecated */ 85 @Deprecated 86 public static final int STATE_YELLOW = 2; 87 88 /** @deprecated */ 89 @Deprecated 90 public static final int STATE_RED = 3; 91 92 /** @deprecated */ 93 @Deprecated getState()94 public static final int getState() { 95 return STATE_GREEN; 96 } 97 98 // Android-removed: Not used. 99 /** @deprecated */ 100 // @Deprecated 101 // public static void registerVMNotification(VMNotification n) { } 102 103 /** @deprecated */ 104 @Deprecated asChange(int as_old, int as_new)105 public static void asChange(int as_old, int as_new) { } 106 107 /** @deprecated */ 108 @Deprecated asChange_otherthread(int as_old, int as_new)109 public static void asChange_otherthread(int as_old, int as_new) { } 110 111 /* 112 * Not supported in 1.2 because these will have to be exported as 113 * JVM functions, and we are not sure we want do that. Leaving 114 * here so it can be easily resurrected -- just remove the // 115 * comments. 116 */ 117 118 /** 119 * Resume Java profiling. All profiling data is added to any 120 * earlier profiling, unless <code>resetJavaProfiler</code> is 121 * called in between. If profiling was not started from the 122 * command line, <code>resumeJavaProfiler</code> will start it. 123 * <p> 124 * 125 * NOTE: Profiling must be enabled from the command line for a 126 * java.prof report to be automatically generated on exit; if not, 127 * writeJavaProfilerReport must be invoked to write a report. 128 * 129 * @see resetJavaProfiler 130 * @see writeJavaProfilerReport 131 */ 132 133 // public native static void resumeJavaProfiler(); 134 135 /** 136 * Suspend Java profiling. 137 */ 138 // public native static void suspendJavaProfiler(); 139 140 /** 141 * Initialize Java profiling. Any accumulated profiling 142 * information is discarded. 143 */ 144 // public native static void resetJavaProfiler(); 145 146 /** 147 * Write the current profiling contents to the file "java.prof". 148 * If the file already exists, it will be overwritten. 149 */ 150 // public native static void writeJavaProfilerReport(); 151 152 153 private static volatile boolean booted = false; 154 private static final Object lock = new Object(); 155 156 // Invoked by by System.initializeSystemClass just before returning. 157 // Subsystems that are invoked during initialization can check this 158 // property in order to avoid doing things that should wait until the 159 // application class loader has been set up. 160 // booted()161 public static void booted() { 162 synchronized (lock) { 163 booted = true; 164 lock.notifyAll(); 165 } 166 } 167 isBooted()168 public static boolean isBooted() { 169 return booted; 170 } 171 172 // Waits until VM completes initialization 173 // 174 // This method is invoked by the Finalizer thread awaitBooted()175 public static void awaitBooted() throws InterruptedException { 176 synchronized (lock) { 177 while (!booted) { 178 lock.wait(); 179 } 180 } 181 } 182 183 // A user-settable upper limit on the maximum amount of allocatable direct 184 // buffer memory. This value may be changed during VM initialization if 185 // "java" is launched with "-XX:MaxDirectMemorySize=<size>". 186 // 187 // The initial value of this field is arbitrary; during JRE initialization 188 // it will be reset to the value specified on the command line, if any, 189 // otherwise to Runtime.getRuntime().maxMemory(). 190 // 191 private static long directMemory = 64 * 1024 * 1024; 192 193 // Returns the maximum amount of allocatable direct buffer memory. 194 // The directMemory variable is initialized during system initialization 195 // in the saveAndRemoveProperties method. 196 // maxDirectMemory()197 public static long maxDirectMemory() { 198 return directMemory; 199 } 200 201 // User-controllable flag that determines if direct buffers should be page 202 // aligned. The "-XX:+PageAlignDirectMemory" option can be used to force 203 // buffers, allocated by ByteBuffer.allocateDirect, to be page aligned. 204 private static boolean pageAlignDirectMemory; 205 206 // Returns {@code true} if the direct buffers should be page aligned. This 207 // variable is initialized by saveAndRemoveProperties. isDirectMemoryPageAligned()208 public static boolean isDirectMemoryPageAligned() { 209 return pageAlignDirectMemory; 210 } 211 212 // A user-settable boolean to determine whether ClassLoader.loadClass should 213 // accept array syntax. This value may be changed during VM initialization 214 // via the system property "sun.lang.ClassLoader.allowArraySyntax". 215 // 216 // The default for 1.5 is "true", array syntax is allowed. In 1.6, the 217 // default will be "false". The presence of this system property to 218 // control array syntax allows applications the ability to preview this new 219 // behaviour. 220 // 221 private static boolean defaultAllowArraySyntax = false; 222 private static boolean allowArraySyntax = defaultAllowArraySyntax; 223 224 // The allowArraySyntax boolean is initialized during system initialization 225 // in the saveAndRemoveProperties method. 226 // 227 // It is initialized based on the value of the system property 228 // "sun.lang.ClassLoader.allowArraySyntax". If the system property is not 229 // provided, the default for 1.5 is "true". In 1.6, the default will be 230 // "false". If the system property is provided, then the value of 231 // allowArraySyntax will be equal to "true" if Boolean.parseBoolean() 232 // returns "true". Otherwise, the field will be set to "false". 233 // allowArraySyntax()234 public static boolean allowArraySyntax() { 235 return allowArraySyntax; 236 } 237 238 // BEGIN Android-removed: Not used on android. 239 /** 240 * Returns true if the given class loader is in the system domain 241 * in which all permissions are granted. 242 */ 243 // public static boolean isSystemDomainLoader(ClassLoader loader) { 244 // return loader == null; 245 // } 246 // END Android-removed: Not used on android. 247 248 /** 249 * Returns the system property of the specified key saved at 250 * system initialization time. This method should only be used 251 * for the system properties that are not changed during runtime. 252 * It accesses a private copy of the system properties so 253 * that user's locking of the system properties object will not 254 * cause the library to deadlock. 255 * 256 * Note that the saved system properties do not include 257 * the ones set by sun.misc.Version.init(). 258 * 259 */ getSavedProperty(String key)260 public static String getSavedProperty(String key) { 261 // TODO(narayan): Why is this commented out ? 262 // if (savedProps.isEmpty()) 263 // throw new IllegalStateException("Should be non-empty if initialized"); 264 265 return savedProps.getProperty(key); 266 } 267 268 // TODO: the Property Management needs to be refactored and 269 // the appropriate prop keys need to be accessible to the 270 // calling classes to avoid duplication of keys. 271 private static final Properties savedProps = new Properties(); 272 273 // Save a private copy of the system properties and remove 274 // the system properties that are not intended for public access. 275 // 276 // This method can only be invoked during system initialization. saveAndRemoveProperties(Properties props)277 public static void saveAndRemoveProperties(Properties props) { 278 if (booted) 279 throw new IllegalStateException("System initialization has completed"); 280 281 savedProps.putAll(props); 282 283 // Set the maximum amount of direct memory. This value is controlled 284 // by the vm option -XX:MaxDirectMemorySize=<size>. 285 // The maximum amount of allocatable direct buffer memory (in bytes) 286 // from the system property sun.nio.MaxDirectMemorySize set by the VM. 287 // The system property will be removed. 288 String s = (String)props.remove("sun.nio.MaxDirectMemorySize"); 289 if (s != null) { 290 if (s.equals("-1")) { 291 // -XX:MaxDirectMemorySize not given, take default 292 directMemory = Runtime.getRuntime().maxMemory(); 293 } else { 294 long l = Long.parseLong(s); 295 if (l > -1) 296 directMemory = l; 297 } 298 } 299 300 // Check if direct buffers should be page aligned 301 s = (String)props.remove("sun.nio.PageAlignDirectMemory"); 302 if ("true".equals(s)) 303 pageAlignDirectMemory = true; 304 305 // Set a boolean to determine whether ClassLoader.loadClass accepts 306 // array syntax. This value is controlled by the system property 307 // "sun.lang.ClassLoader.allowArraySyntax". 308 s = props.getProperty("sun.lang.ClassLoader.allowArraySyntax"); 309 allowArraySyntax = (s == null 310 ? defaultAllowArraySyntax 311 : Boolean.parseBoolean(s)); 312 313 // Remove other private system properties 314 // used by java.lang.Integer.IntegerCache 315 props.remove("java.lang.Integer.IntegerCache.high"); 316 317 // used by java.util.zip.ZipFile 318 props.remove("sun.zip.disableMemoryMapping"); 319 320 // used by sun.launcher.LauncherHelper 321 props.remove("sun.java.launcher.diag"); 322 323 // used by sun.misc.URLClassPath 324 props.remove("sun.cds.enableSharedLookupCache"); 325 } 326 327 // Initialize any miscellenous operating system settings that need to be 328 // set for the class libraries. 329 // initializeOSEnvironment()330 public static void initializeOSEnvironment() { 331 // Android-removed: OSEnvironment.initialize() not supported 332 //if (!booted) { 333 // OSEnvironment.initialize(); 334 //} 335 } 336 337 /* Current count of objects pending for finalization */ 338 private static volatile int finalRefCount = 0; 339 340 /* Peak count of objects pending for finalization */ 341 private static volatile int peakFinalRefCount = 0; 342 343 /* 344 * Gets the number of objects pending for finalization. 345 * 346 * @return the number of objects pending for finalization. 347 */ getFinalRefCount()348 public static int getFinalRefCount() { 349 return finalRefCount; 350 } 351 352 /* 353 * Gets the peak number of objects pending for finalization. 354 * 355 * @return the peak number of objects pending for finalization. 356 */ getPeakFinalRefCount()357 public static int getPeakFinalRefCount() { 358 return peakFinalRefCount; 359 } 360 361 /* 362 * Add <tt>n</tt> to the objects pending for finalization count. 363 * 364 * @param n an integer value to be added to the objects pending 365 * for finalization count 366 */ addFinalRefCount(int n)367 public static void addFinalRefCount(int n) { 368 // The caller must hold lock to synchronize the update. 369 370 finalRefCount += n; 371 if (finalRefCount > peakFinalRefCount) { 372 peakFinalRefCount = finalRefCount; 373 } 374 } 375 376 /** 377 * Returns Thread.State for the given threadStatus 378 */ toThreadState(int threadStatus)379 public static Thread.State toThreadState(int threadStatus) { 380 if ((threadStatus & JVMTI_THREAD_STATE_RUNNABLE) != 0) { 381 return RUNNABLE; 382 } else if ((threadStatus & JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER) != 0) { 383 return BLOCKED; 384 } else if ((threadStatus & JVMTI_THREAD_STATE_WAITING_INDEFINITELY) != 0) { 385 return WAITING; 386 } else if ((threadStatus & JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT) != 0) { 387 return TIMED_WAITING; 388 } else if ((threadStatus & JVMTI_THREAD_STATE_TERMINATED) != 0) { 389 return TERMINATED; 390 } else if ((threadStatus & JVMTI_THREAD_STATE_ALIVE) == 0) { 391 return NEW; 392 } else { 393 return RUNNABLE; 394 } 395 } 396 397 /* The threadStatus field is set by the VM at state transition 398 * in the hotspot implementation. Its value is set according to 399 * the JVM TI specification GetThreadState function. 400 */ 401 private final static int JVMTI_THREAD_STATE_ALIVE = 0x0001; 402 private final static int JVMTI_THREAD_STATE_TERMINATED = 0x0002; 403 private final static int JVMTI_THREAD_STATE_RUNNABLE = 0x0004; 404 private final static int JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400; 405 private final static int JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010; 406 private final static int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020; 407 408 // Android-changed: Add @CriticalNative for performance to be consistent with System.currentTimeMillis(). 409 /** 410 * Get a nanosecond time stamp adjustment in the form of a single long. 411 * 412 * This value can be used to create an instant using 413 * {@link java.time.Instant#ofEpochSecond(long, long) 414 * java.time.Instant.ofEpochSecond(offsetInSeconds, 415 * getNanoTimeAdjustment(offsetInSeconds))}. 416 * <p> 417 * The value returned has the best resolution available to the JVM on 418 * the current system. 419 * This is usually down to microseconds - or tenth of microseconds - 420 * depending on the OS/Hardware and the JVM implementation. 421 * 422 * @param offsetInSeconds The offset in seconds from which the nanosecond 423 * time stamp should be computed. 424 * 425 * @apiNote The offset should be recent enough - so that 426 * {@code offsetInSeconds} is within {@code +/- 2^32} seconds of the 427 * current UTC time. If the offset is too far off, {@code -1} will be 428 * returned. As such, {@code -1} must not be considered as a valid 429 * nano time adjustment, but as an exception value indicating 430 * that an offset closer to the current time should be used. 431 * 432 * @return A nanosecond time stamp adjustment in the form of a single long. 433 * If the offset is too far off the current time, this method returns -1. 434 * In that case, the caller should call this method again, passing a 435 * more accurate offset. 436 */ 437 @CriticalNative getNanoTimeAdjustment(long offsetInSeconds)438 public static native long getNanoTimeAdjustment(long offsetInSeconds); 439 440 // BEGIN Android-removed: latestUserDefinedLoader()/initialize() not supported. 441 // /* 442 // * Returns the first non-null class loader up the execution stack, 443 // * or null if only code from the null class loader is on the stack. 444 // */ 445 // public static native ClassLoader latestUserDefinedLoader(); 446 447 // static { 448 // initialize(); 449 // } 450 // private native static void initialize(); 451 // END Android-removed: latestUserDefinedLoader()/initialize() not supported. 452 453 // BEGIN Android-removed: initializeFromArchive() not supported. 454 /* 455 * Initialize archived static fields in the given Class using archived 456 * values from CDS dump time. Also initialize the classes of objects in 457 * the archived graph referenced by those fields. 458 * 459 * Those static fields remain as uninitialized if there is no mapped CDS 460 * java heap data or there is any error during initialization of the 461 * object class in the archived graph. 462 * 463 public static native void initializeFromArchive(Class<?> c); 464 */ 465 // END Android-removed: initializeFromArchive() not supported. 466 } 467