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