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