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 jdk.internal.util.StaticProperty; 29 30 import static java.lang.Thread.State.*; 31 32 import java.io.File; 33 import java.util.Collections; 34 import java.util.Map; 35 import java.util.Properties; 36 37 public class VM { 38 39 // the init level when the VM is fully initialized 40 private static final int JAVA_LANG_SYSTEM_INITED = 1; 41 private static final int MODULE_SYSTEM_INITED = 2; 42 private static final int SYSTEM_LOADER_INITIALIZING = 3; 43 private static final int SYSTEM_BOOTED = 4; 44 private static final int SYSTEM_SHUTDOWN = 5; 45 46 47 // 0, 1, 2, ... 48 private static volatile int initLevel; 49 private static final Object lock = new Object(); 50 51 /** 52 * Sets the init level. 53 * 54 * @see java.lang.System#initPhase1 55 * @see java.lang.System#initPhase2 56 * @see java.lang.System#initPhase3 57 */ 58 public static void initLevel(int value) { 59 synchronized (lock) { 60 if (value <= initLevel || value > SYSTEM_SHUTDOWN) 61 throw new InternalError("Bad level: " + value); 62 initLevel = value; 63 lock.notifyAll(); 64 } 65 } 66 67 /** 68 * Returns the current init level. 69 */ 70 public static int initLevel() { 71 return initLevel; 72 } 73 74 /** 75 * Waits for the init level to get the given value. 76 * 77 * @see java.lang.ref.Finalizer 78 */ 79 public static void awaitInitLevel(int value) throws InterruptedException { 80 synchronized (lock) { 81 while (initLevel < value) { 82 lock.wait(); 83 } 84 } 85 } 86 87 /** 88 * Returns {@code true} if the module system has been initialized. 89 * @see java.lang.System#initPhase2 90 */ 91 public static boolean isModuleSystemInited() { 92 return VM.initLevel() >= MODULE_SYSTEM_INITED; 93 } 94 95 /** 96 * Returns {@code true} if the VM is fully initialized. 97 */ 98 public static boolean isBooted() { 99 return initLevel >= SYSTEM_BOOTED; 100 } 101 102 /** 103 * Set shutdown state. Shutdown completes when all registered shutdown 104 * hooks have been run. 105 * 106 * @see java.lang.Shutdown 107 */ 108 public static void shutdown() { 109 initLevel(SYSTEM_SHUTDOWN); 110 } 111 112 /** 113 * Returns {@code true} if the VM has been shutdown 114 */ 115 public static boolean isShutdown() { 116 return initLevel == SYSTEM_SHUTDOWN; 117 } 118 119 // A user-settable upper limit on the maximum amount of allocatable direct 120 // buffer memory. This value may be changed during VM initialization if 121 // "java" is launched with "-XX:MaxDirectMemorySize=<size>". 122 // 123 // The initial value of this field is arbitrary; during JRE initialization 124 // it will be reset to the value specified on the command line, if any, 125 // otherwise to Runtime.getRuntime().maxMemory(). 126 // 127 private static long directMemory = 64 * 1024 * 1024; 128 129 // Returns the maximum amount of allocatable direct buffer memory. 130 // The directMemory variable is initialized during system initialization 131 // in the saveAndRemoveProperties method. 132 // 133 public static long maxDirectMemory() { 134 return directMemory; 135 } 136 137 // User-controllable flag that determines if direct buffers should be page 138 // aligned. The "-XX:+PageAlignDirectMemory" option can be used to force 139 // buffers, allocated by ByteBuffer.allocateDirect, to be page aligned. 140 private static boolean pageAlignDirectMemory; 141 142 // Returns {@code true} if the direct buffers should be page aligned. This 143 // variable is initialized by saveAndRemoveProperties. 144 public static boolean isDirectMemoryPageAligned() { 145 return pageAlignDirectMemory; 146 } 147 148 /** 149 * Returns true if the given class loader is the bootstrap class loader 150 * or the platform class loader. 151 */ 152 public static boolean isSystemDomainLoader(ClassLoader loader) { 153 return loader == null || loader == ClassLoader.getPlatformClassLoader(); 154 } 155 156 /** 157 * Returns the system property of the specified key saved at 158 * system initialization time. This method should only be used 159 * for the system properties that are not changed during runtime. 160 * 161 * Note that the saved system properties do not include 162 * the ones set by java.lang.VersionProps.init(). 163 */ 164 public static String getSavedProperty(String key) { 165 if (savedProps == null) 166 throw new IllegalStateException("Not yet initialized"); 167 168 return savedProps.get(key); 169 } 170 171 /** 172 * Gets an unmodifiable view of the system properties saved at system 173 * initialization time. This method should only be used 174 * for the system properties that are not changed during runtime. 175 * 176 * Note that the saved system properties do not include 177 * the ones set by java.lang.VersionProps.init(). 178 */ 179 public static Map<String, String> getSavedProperties() { 180 if (savedProps == null) 181 throw new IllegalStateException("Not yet initialized"); 182 183 return Collections.unmodifiableMap(savedProps); 184 } 185 186 private static Map<String, String> savedProps; 187 188 // Save a private copy of the system properties and remove 189 // the system properties that are not intended for public access. 190 // 191 // This method can only be invoked during system initialization. 192 public static void saveProperties(Map<String, String> props) { 193 if (initLevel() != 0) 194 throw new IllegalStateException("Wrong init level"); 195 196 // only main thread is running at this time, so savedProps and 197 // its content will be correctly published to threads started later 198 if (savedProps == null) { 199 savedProps = props; 200 } 201 202 // Set the maximum amount of direct memory. This value is controlled 203 // by the vm option -XX:MaxDirectMemorySize=<size>. 204 // The maximum amount of allocatable direct buffer memory (in bytes) 205 // from the system property sun.nio.MaxDirectMemorySize set by the VM. 206 // If not set or set to -1, the max memory will be used 207 // The system property will be removed. 208 String s = props.get("sun.nio.MaxDirectMemorySize"); 209 if (s == null || s.isEmpty() || s.equals("-1")) { 210 // -XX:MaxDirectMemorySize not given, take default 211 directMemory = Runtime.getRuntime().maxMemory(); 212 } else { 213 long l = Long.parseLong(s); 214 if (l > -1) 215 directMemory = l; 216 } 217 218 // Check if direct buffers should be page aligned 219 s = props.get("sun.nio.PageAlignDirectMemory"); 220 if ("true".equals(s)) 221 pageAlignDirectMemory = true; 222 } 223 224 // Initialize any miscellaneous operating system settings that need to be 225 // set for the class libraries. 226 // 227 public static void initializeOSEnvironment() { 228 if (initLevel() == 0) { 229 OSEnvironment.initialize(); 230 } 231 } 232 233 /* Current count of objects pending for finalization */ 234 private static volatile int finalRefCount; 235 236 /* Peak count of objects pending for finalization */ 237 private static volatile int peakFinalRefCount; 238 239 /* 240 * Gets the number of objects pending for finalization. 241 * 242 * @return the number of objects pending for finalization. 243 */ 244 public static int getFinalRefCount() { 245 return finalRefCount; 246 } 247 248 /* 249 * Gets the peak number of objects pending for finalization. 250 * 251 * @return the peak number of objects pending for finalization. 252 */ 253 public static int getPeakFinalRefCount() { 254 return peakFinalRefCount; 255 } 256 257 /* 258 * Add {@code n} to the objects pending for finalization count. 259 * 260 * @param n an integer value to be added to the objects pending 261 * for finalization count 262 */ 263 public static void addFinalRefCount(int n) { 264 // The caller must hold lock to synchronize the update. 265 266 finalRefCount += n; 267 if (finalRefCount > peakFinalRefCount) { 268 peakFinalRefCount = finalRefCount; 269 } 270 } 271 272 /** 273 * Returns Thread.State for the given threadStatus 274 */ 275 public static Thread.State toThreadState(int threadStatus) { 276 if ((threadStatus & JVMTI_THREAD_STATE_RUNNABLE) != 0) { 277 return RUNNABLE; 278 } else if ((threadStatus & JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER) != 0) { 279 return BLOCKED; 280 } else if ((threadStatus & JVMTI_THREAD_STATE_WAITING_INDEFINITELY) != 0) { 281 return WAITING; 282 } else if ((threadStatus & JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT) != 0) { 283 return TIMED_WAITING; 284 } else if ((threadStatus & JVMTI_THREAD_STATE_TERMINATED) != 0) { 285 return TERMINATED; 286 } else if ((threadStatus & JVMTI_THREAD_STATE_ALIVE) == 0) { 287 return NEW; 288 } else { 289 return RUNNABLE; 290 } 291 } 292 293 /* The threadStatus field is set by the VM at state transition 294 * in the hotspot implementation. Its value is set according to 295 * the JVM TI specification GetThreadState function. 296 */ 297 private static final int JVMTI_THREAD_STATE_ALIVE = 0x0001; 298 private static final int JVMTI_THREAD_STATE_TERMINATED = 0x0002; 299 private static final int JVMTI_THREAD_STATE_RUNNABLE = 0x0004; 300 private static final int JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400; 301 private static final int JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010; 302 private static final int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020; 303 304 /* 305 * Returns the first user-defined class loader up the execution stack, 306 * or the platform class loader if only code from the platform or 307 * bootstrap class loader is on the stack. 308 */ 309 public static ClassLoader latestUserDefinedLoader() { 310 ClassLoader loader = latestUserDefinedLoader0(); 311 return loader != null ? loader : ClassLoader.getPlatformClassLoader(); 312 } 313 314 /* 315 * Returns the first user-defined class loader up the execution stack, 316 * or null if only code from the platform or bootstrap class loader is 317 * on the stack. VM does not keep a reference of platform loader and so 318 * it returns null. 319 * 320 * This method should be replaced with StackWalker::walk and then we can 321 * remove the logic in the VM. 322 */ 323 private static native ClassLoader latestUserDefinedLoader0(); 324 325 /** 326 * Returns {@code true} if we are in a set UID program. 327 */ 328 public static boolean isSetUID() { 329 long uid = getuid(); 330 long euid = geteuid(); 331 long gid = getgid(); 332 long egid = getegid(); 333 return uid != euid || gid != egid; 334 } 335 336 /** 337 * Returns the real user ID of the calling process, 338 * or -1 if the value is not available. 339 */ 340 public static native long getuid(); 341 342 /** 343 * Returns the effective user ID of the calling process, 344 * or -1 if the value is not available. 345 */ 346 public static native long geteuid(); 347 348 /** 349 * Returns the real group ID of the calling process, 350 * or -1 if the value is not available. 351 */ 352 public static native long getgid(); 353 354 /** 355 * Returns the effective group ID of the calling process, 356 * or -1 if the value is not available. 357 */ 358 public static native long getegid(); 359 360 /** 361 * Get a nanosecond time stamp adjustment in the form of a single long. 362 * 363 * This value can be used to create an instant using 364 * {@link java.time.Instant#ofEpochSecond(long, long) 365 * java.time.Instant.ofEpochSecond(offsetInSeconds, 366 * getNanoTimeAdjustment(offsetInSeconds))}. 367 * <p> 368 * The value returned has the best resolution available to the JVM on 369 * the current system. 370 * This is usually down to microseconds - or tenth of microseconds - 371 * depending on the OS/Hardware and the JVM implementation. 372 * 373 * @param offsetInSeconds The offset in seconds from which the nanosecond 374 * time stamp should be computed. 375 * 376 * @apiNote The offset should be recent enough - so that 377 * {@code offsetInSeconds} is within {@code +/- 2^32} seconds of the 378 * current UTC time. If the offset is too far off, {@code -1} will be 379 * returned. As such, {@code -1} must not be considered as a valid 380 * nano time adjustment, but as an exception value indicating 381 * that an offset closer to the current time should be used. 382 * 383 * @return A nanosecond time stamp adjustment in the form of a single long. 384 * If the offset is too far off the current time, this method returns -1. 385 * In that case, the caller should call this method again, passing a 386 * more accurate offset. 387 */ 388 public static native long getNanoTimeAdjustment(long offsetInSeconds); 389 390 /** 391 * Returns the VM arguments for this runtime environment. 392 * 393 * @implNote 394 * The HotSpot JVM processes the input arguments from multiple sources 395 * in the following order: 396 * 1. JAVA_TOOL_OPTIONS environment variable 397 * 2. Options from JNI Invocation API 398 * 3. _JAVA_OPTIONS environment variable 399 * 400 * If VM options file is specified via -XX:VMOptionsFile, the vm options 401 * file is read and expanded in place of -XX:VMOptionFile option. 402 */ 403 public static native String[] getRuntimeArguments(); 404 405 static { 406 initialize(); 407 } 408 private static native void initialize(); 409 410 /** 411 * Initialize archived static fields in the given Class using archived 412 * values from CDS dump time. Also initialize the classes of objects in 413 * the archived graph referenced by those fields. 414 * 415 * Those static fields remain as uninitialized if there is no mapped CDS 416 * java heap data or there is any error during initialization of the 417 * object class in the archived graph. 418 */ 419 public static native void initializeFromArchive(Class<?> c); 420 421 /** 422 * Get the time at which the archive was created 423 */ 424 public static long archiveLastModified() { 425 String sep = File.separator; 426 return new File(StaticProperty.javaHome() + sep + "lib" + sep + 427 "server" + sep + "classes.jsa").lastModified(); 428 } 429 }