Path: blob/master/src/java.base/share/classes/jdk/internal/misc/VM.java
41159 views
/*1* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package jdk.internal.misc;2627import static java.lang.Thread.State.*;2829import java.text.NumberFormat;30import java.util.ArrayList;31import java.util.Collections;32import java.util.List;33import java.util.Map;3435import jdk.internal.access.SharedSecrets;3637import sun.nio.ch.FileChannelImpl;3839public class VM {4041// the init level when the VM is fully initialized42private static final int JAVA_LANG_SYSTEM_INITED = 1;43private static final int MODULE_SYSTEM_INITED = 2;44private static final int SYSTEM_LOADER_INITIALIZING = 3;45private static final int SYSTEM_BOOTED = 4;46private static final int SYSTEM_SHUTDOWN = 5;4748// 0, 1, 2, ...49private static volatile int initLevel;50private static final Object lock = new Object();5152/**53* Sets the init level.54*55* @see java.lang.System#initPhase156* @see java.lang.System#initPhase257* @see java.lang.System#initPhase358*/59public static void initLevel(int value) {60synchronized (lock) {61if (value <= initLevel || value > SYSTEM_SHUTDOWN)62throw new InternalError("Bad level: " + value);63initLevel = value;64lock.notifyAll();65}66}6768/**69* Returns the current init level.70*/71public static int initLevel() {72return initLevel;73}7475/**76* Waits for the init level to get the given value.77*78* @see java.lang.ref.Finalizer79*/80public static void awaitInitLevel(int value) throws InterruptedException {81synchronized (lock) {82while (initLevel < value) {83lock.wait();84}85}86}8788/**89* Returns {@code true} if the module system has been initialized.90* @see java.lang.System#initPhase291*/92public static boolean isModuleSystemInited() {93return VM.initLevel() >= MODULE_SYSTEM_INITED;94}9596/**97* Returns {@code true} if the VM is fully initialized.98*/99public static boolean isBooted() {100return initLevel >= SYSTEM_BOOTED;101}102103/**104* Set shutdown state. Shutdown completes when all registered shutdown105* hooks have been run.106*107* @see java.lang.Shutdown108*/109public static void shutdown() {110initLevel(SYSTEM_SHUTDOWN);111}112113/**114* Returns {@code true} if the VM has been shutdown115*/116public static boolean isShutdown() {117return initLevel == SYSTEM_SHUTDOWN;118}119120// A user-settable upper limit on the maximum amount of allocatable direct121// buffer memory. This value may be changed during VM initialization if122// "java" is launched with "-XX:MaxDirectMemorySize=<size>".123//124// The initial value of this field is arbitrary; during JRE initialization125// it will be reset to the value specified on the command line, if any,126// otherwise to Runtime.getRuntime().maxMemory().127//128private static long directMemory = 64 * 1024 * 1024;129130// Returns the maximum amount of allocatable direct buffer memory.131// The directMemory variable is initialized during system initialization132// in the saveAndRemoveProperties method.133//134public static long maxDirectMemory() {135return directMemory;136}137138// User-controllable flag that determines if direct buffers should be page139// aligned. The "-XX:+PageAlignDirectMemory" option can be used to force140// buffers, allocated by ByteBuffer.allocateDirect, to be page aligned.141private static boolean pageAlignDirectMemory;142143// Returns {@code true} if the direct buffers should be page aligned. This144// variable is initialized by saveAndRemoveProperties.145public static boolean isDirectMemoryPageAligned() {146return pageAlignDirectMemory;147}148149private static int classFileMajorVersion;150private static int classFileMinorVersion;151private static final int PREVIEW_MINOR_VERSION = 65535;152153/**154* Tests if the given version is a supported {@code class}155* file version.156*157* A {@code class} file depends on the preview features of Java SE {@code N}158* if the major version is {@code N} and the minor version is 65535.159* This method returns {@code true} if the given version is a supported160* {@code class} file version regardless of whether the preview features161* are enabled or not.162*163* @jvms 4.1 Table 4.1-A. class file format major versions164*/165public static boolean isSupportedClassFileVersion(int major, int minor) {166if (major < 45 || major > classFileMajorVersion) return false;167// for major version is between 45 and 55 inclusive, the minor version may be any value168if (major < 56) return true;169// otherwise, the minor version must be 0 or 65535170return minor == 0 || minor == PREVIEW_MINOR_VERSION;171}172173/**174* Tests if the given version is a supported {@code class}175* file version for module descriptor.176*177* major.minor version >= 53.0178*/179public static boolean isSupportedModuleDescriptorVersion(int major, int minor) {180if (major < 53 || major > classFileMajorVersion) return false;181// for major version is between 45 and 55 inclusive, the minor version may be any value182if (major < 56) return true;183// otherwise, the minor version must be 0 or 65535184// preview features do not apply to module-info.class but JVMS allows it185return minor == 0 || minor == PREVIEW_MINOR_VERSION;186}187188/**189* Returns true if the given class loader is the bootstrap class loader190* or the platform class loader.191*/192public static boolean isSystemDomainLoader(ClassLoader loader) {193return loader == null || loader == ClassLoader.getPlatformClassLoader();194}195196/**197* Returns the system property of the specified key saved at198* system initialization time. This method should only be used199* for the system properties that are not changed during runtime.200*201* Note that the saved system properties do not include202* the ones set by java.lang.VersionProps.init().203*/204public static String getSavedProperty(String key) {205if (savedProps == null)206throw new IllegalStateException("Not yet initialized");207208return savedProps.get(key);209}210211/**212* Gets an unmodifiable view of the system properties saved at system213* initialization time. This method should only be used214* for the system properties that are not changed during runtime.215*216* Note that the saved system properties do not include217* the ones set by java.lang.VersionProps.init().218*/219public static Map<String, String> getSavedProperties() {220if (savedProps == null)221throw new IllegalStateException("Not yet initialized");222223return Collections.unmodifiableMap(savedProps);224}225226private static Map<String, String> savedProps;227228// Save a private copy of the system properties and remove229// the system properties that are not intended for public access.230//231// This method can only be invoked during system initialization.232public static void saveProperties(Map<String, String> props) {233if (initLevel() != 0)234throw new IllegalStateException("Wrong init level");235236// only main thread is running at this time, so savedProps and237// its content will be correctly published to threads started later238if (savedProps == null) {239savedProps = props;240}241242// Set the maximum amount of direct memory. This value is controlled243// by the vm option -XX:MaxDirectMemorySize=<size>.244// The maximum amount of allocatable direct buffer memory (in bytes)245// from the system property sun.nio.MaxDirectMemorySize set by the VM.246// If not set or set to -1, the max memory will be used247// The system property will be removed.248String s = props.get("sun.nio.MaxDirectMemorySize");249if (s == null || s.isEmpty() || s.equals("-1")) {250// -XX:MaxDirectMemorySize not given, take default251directMemory = Runtime.getRuntime().maxMemory();252} else {253long l = Long.parseLong(s);254if (l > -1)255directMemory = l;256}257258// Check if direct buffers should be page aligned259s = props.get("sun.nio.PageAlignDirectMemory");260if ("true".equals(s))261pageAlignDirectMemory = true;262263s = props.get("java.class.version");264int index = s.indexOf('.');265try {266classFileMajorVersion = Integer.valueOf(s.substring(0, index));267classFileMinorVersion = Integer.valueOf(s.substring(index+1, s.length()));268} catch (NumberFormatException e) {269throw new InternalError(e);270}271}272273// Initialize any miscellaneous operating system settings that need to be274// set for the class libraries.275//276public static void initializeOSEnvironment() {277if (initLevel() == 0) {278OSEnvironment.initialize();279}280}281282/* Current count of objects pending for finalization */283private static volatile int finalRefCount;284285/* Peak count of objects pending for finalization */286private static volatile int peakFinalRefCount;287288/*289* Gets the number of objects pending for finalization.290*291* @return the number of objects pending for finalization.292*/293public static int getFinalRefCount() {294return finalRefCount;295}296297/*298* Gets the peak number of objects pending for finalization.299*300* @return the peak number of objects pending for finalization.301*/302public static int getPeakFinalRefCount() {303return peakFinalRefCount;304}305306/*307* Add {@code n} to the objects pending for finalization count.308*309* @param n an integer value to be added to the objects pending310* for finalization count311*/312public static void addFinalRefCount(int n) {313// The caller must hold lock to synchronize the update.314315finalRefCount += n;316if (finalRefCount > peakFinalRefCount) {317peakFinalRefCount = finalRefCount;318}319}320321/**322* Returns Thread.State for the given threadStatus323*/324public static Thread.State toThreadState(int threadStatus) {325if ((threadStatus & JVMTI_THREAD_STATE_RUNNABLE) != 0) {326return RUNNABLE;327} else if ((threadStatus & JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER) != 0) {328return BLOCKED;329} else if ((threadStatus & JVMTI_THREAD_STATE_WAITING_INDEFINITELY) != 0) {330return WAITING;331} else if ((threadStatus & JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT) != 0) {332return TIMED_WAITING;333} else if ((threadStatus & JVMTI_THREAD_STATE_TERMINATED) != 0) {334return TERMINATED;335} else if ((threadStatus & JVMTI_THREAD_STATE_ALIVE) == 0) {336return NEW;337} else {338return RUNNABLE;339}340}341342/* The threadStatus field is set by the VM at state transition343* in the hotspot implementation. Its value is set according to344* the JVM TI specification GetThreadState function.345*/346private static final int JVMTI_THREAD_STATE_ALIVE = 0x0001;347private static final int JVMTI_THREAD_STATE_TERMINATED = 0x0002;348private static final int JVMTI_THREAD_STATE_RUNNABLE = 0x0004;349private static final int JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400;350private static final int JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010;351private static final int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020;352353/*354* Returns the first user-defined class loader up the execution stack,355* or the platform class loader if only code from the platform or356* bootstrap class loader is on the stack.357*/358public static ClassLoader latestUserDefinedLoader() {359ClassLoader loader = latestUserDefinedLoader0();360return loader != null ? loader : ClassLoader.getPlatformClassLoader();361}362363/*364* Returns the first user-defined class loader up the execution stack,365* or null if only code from the platform or bootstrap class loader is366* on the stack. VM does not keep a reference of platform loader and so367* it returns null.368*369* This method should be replaced with StackWalker::walk and then we can370* remove the logic in the VM.371*/372private static native ClassLoader latestUserDefinedLoader0();373374/**375* Returns {@code true} if we are in a set UID program.376*/377public static boolean isSetUID() {378long uid = getuid();379long euid = geteuid();380long gid = getgid();381long egid = getegid();382return uid != euid || gid != egid;383}384385/**386* Returns the real user ID of the calling process,387* or -1 if the value is not available.388*/389public static native long getuid();390391/**392* Returns the effective user ID of the calling process,393* or -1 if the value is not available.394*/395public static native long geteuid();396397/**398* Returns the real group ID of the calling process,399* or -1 if the value is not available.400*/401public static native long getgid();402403/**404* Returns the effective group ID of the calling process,405* or -1 if the value is not available.406*/407public static native long getegid();408409/**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 using413* {@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 on418* 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 nanosecond423* time stamp should be computed.424*425* @apiNote The offset should be recent enough - so that426* {@code offsetInSeconds} is within {@code +/- 2^32} seconds of the427* current UTC time. If the offset is too far off, {@code -1} will be428* returned. As such, {@code -1} must not be considered as a valid429* nano time adjustment, but as an exception value indicating430* 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 a435* more accurate offset.436*/437public static native long getNanoTimeAdjustment(long offsetInSeconds);438439/**440* Returns the VM arguments for this runtime environment.441*442* @implNote443* The HotSpot JVM processes the input arguments from multiple sources444* in the following order:445* 1. JAVA_TOOL_OPTIONS environment variable446* 2. Options from JNI Invocation API447* 3. _JAVA_OPTIONS environment variable448*449* If VM options file is specified via -XX:VMOptionsFile, the vm options450* file is read and expanded in place of -XX:VMOptionFile option.451*/452public static native String[] getRuntimeArguments();453454static {455initialize();456}457private static native void initialize();458459/**460* Provides access to information on buffer usage.461*/462public interface BufferPool {463String getName();464long getCount();465long getTotalCapacity();466long getMemoryUsed();467}468469private static class BufferPoolsHolder {470static final List<BufferPool> BUFFER_POOLS;471472static {473ArrayList<BufferPool> bufferPools = new ArrayList<>(3);474bufferPools.add(SharedSecrets.getJavaNioAccess().getDirectBufferPool());475bufferPools.add(FileChannelImpl.getMappedBufferPool());476bufferPools.add(FileChannelImpl.getSyncMappedBufferPool());477478BUFFER_POOLS = Collections.unmodifiableList(bufferPools);479}480}481482/**483* @return the list of buffer pools.484*/485public static List<BufferPool> getBufferPools() {486return BufferPoolsHolder.BUFFER_POOLS;487}488}489490491