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