1 /*
   2  * Copyright (c) 1996, 2015, 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 following methods used to be native methods that instruct
  34      * the VM to selectively suspend certain threads in low-memory
  35      * situations. They are inherently dangerous and not implementable
  36      * on native threads. We removed them in JDK 1.2. The skeletons
  37      * remain so that existing applications that use these methods
  38      * will still work.
  39      */
  40     private static boolean suspended = false;
  41 
  42     /** @deprecated */
  43     @Deprecated
  44     public static boolean threadsSuspended() {
  45         return suspended;
  46     }
  47 
  48     @SuppressWarnings("deprecation")
  49     public static boolean allowThreadSuspension(ThreadGroup g, boolean b) {
  50         return g.allowThreadSuspension(b);
  51     }
  52 
  53     /** @deprecated */
  54     @Deprecated
  55     public static boolean suspendThreads() {
  56         suspended = true;
  57         return true;
  58     }
  59 
  60     // Causes any suspended threadgroups to be resumed.
  61     /** @deprecated */
  62     @Deprecated
  63     public static void unsuspendThreads() {
  64         suspended = false;
  65     }
  66 
  67     // Causes threadgroups no longer marked suspendable to be resumed.
  68     /** @deprecated */
  69     @Deprecated
  70     public static void unsuspendSomeThreads() {
  71     }
  72 
  73     /* Deprecated fields and methods -- Memory advice not supported in 1.2 */
  74 
  75     /** @deprecated */
  76     @Deprecated
  77     public static final int STATE_GREEN = 1;
  78 
  79     /** @deprecated */
  80     @Deprecated
  81     public static final int STATE_YELLOW = 2;
  82 
  83     /** @deprecated */
  84     @Deprecated
  85     public static final int STATE_RED = 3;
  86 
  87     /** @deprecated */
  88     @Deprecated
  89     public static final int getState() {
  90         return STATE_GREEN;
  91     }
  92 
  93     /** @deprecated */
  94     @Deprecated
  95     public static void registerVMNotification(VMNotification n) { }
  96 
  97     /** @deprecated */
  98     @Deprecated
  99     public static void asChange(int as_old, int as_new) { }
 100 
 101     /** @deprecated */
 102     @Deprecated
 103     public static void asChange_otherthread(int as_old, int as_new) { }
 104 
 105     /*
 106      * Not supported in 1.2 because these will have to be exported as
 107      * JVM functions, and we are not sure we want do that. Leaving
 108      * here so it can be easily resurrected -- just remove the //
 109      * comments.
 110      */
 111 
 112     /**
 113      * Resume Java profiling.  All profiling data is added to any
 114      * earlier profiling, unless <code>resetJavaProfiler</code> is
 115      * called in between.  If profiling was not started from the
 116      * command line, <code>resumeJavaProfiler</code> will start it.
 117      * <p>
 118      *
 119      * NOTE: Profiling must be enabled from the command line for a
 120      * java.prof report to be automatically generated on exit; if not,
 121      * writeJavaProfilerReport must be invoked to write a report.
 122      *
 123      * @see     resetJavaProfiler
 124      * @see     writeJavaProfilerReport
 125      */
 126 
 127     // public native static void resumeJavaProfiler();
 128 
 129     /**
 130      * Suspend Java profiling.
 131      */
 132     // public native static void suspendJavaProfiler();
 133 
 134     /**
 135      * Initialize Java profiling.  Any accumulated profiling
 136      * information is discarded.
 137      */
 138     // public native static void resetJavaProfiler();
 139 
 140     /**
 141      * Write the current profiling contents to the file "java.prof".
 142      * If the file already exists, it will be overwritten.
 143      */
 144     // public native static void writeJavaProfilerReport();
 145 
 146 
 147     // the init level when the VM is fully initialized
 148     private static final int JAVA_LANG_SYSTEM_INITED     = 1;
 149     private static final int MODULE_SYSTEM_INITED        = 2;
 150     private static final int SYSTEM_LOADER_INITIALIZING  = 3;
 151     private static final int SYSTEM_BOOTED               = 4;
 152 
 153     // 0, 1, 2, ...
 154     private static volatile int initLevel;
 155     private static final Object lock = new Object();
 156 
 157     /**
 158      * Sets the init level.
 159      *
 160      * @see java.lang.System#initPhase1
 161      * @see java.lang.System#initPhase2
 162      * @see java.lang.System#initPhase3
 163      */
 164     public static void initLevel(int value) {
 165         synchronized (lock) {
 166             if (value <= initLevel || value > SYSTEM_BOOTED)
 167                 throw new InternalError("Bad level: " + value);
 168             initLevel = value;
 169             lock.notifyAll();
 170         }
 171     }
 172 
 173     /**
 174      * Returns the current init level.
 175      */
 176     public static int initLevel() {
 177         return initLevel;
 178     }
 179 
 180     /**
 181      * Waits for the init level to get the given value.
 182      *
 183      * @see java.lang.ref.Finalizer
 184      */
 185     public static void awaitInitLevel(int value) throws InterruptedException {
 186         synchronized (lock) {
 187             while (initLevel < value) {
 188                 lock.wait();
 189             }
 190         }
 191     }
 192 
 193     /**
 194      * Returns {@code true} if the module system has been initialized.
 195      * @see java.lang.System#initPhase2
 196      */
 197     public static boolean isModuleSystemInited() {
 198         return VM.initLevel() >= MODULE_SYSTEM_INITED;
 199     }
 200 
 201     /**
 202      * Returns {@code true} if the VM is fully initialized.
 203      */
 204     public static boolean isBooted() {
 205         return initLevel >= SYSTEM_BOOTED;
 206     }
 207 
 208     // A user-settable upper limit on the maximum amount of allocatable direct
 209     // buffer memory.  This value may be changed during VM initialization if
 210     // "java" is launched with "-XX:MaxDirectMemorySize=<size>".
 211     //
 212     // The initial value of this field is arbitrary; during JRE initialization
 213     // it will be reset to the value specified on the command line, if any,
 214     // otherwise to Runtime.getRuntime().maxMemory().
 215     //
 216     private static long directMemory = 64 * 1024 * 1024;
 217 
 218     // Returns the maximum amount of allocatable direct buffer memory.
 219     // The directMemory variable is initialized during system initialization
 220     // in the saveAndRemoveProperties method.
 221     //
 222     public static long maxDirectMemory() {
 223         return directMemory;
 224     }
 225 
 226     // User-controllable flag that determines if direct buffers should be page
 227     // aligned. The "-XX:+PageAlignDirectMemory" option can be used to force
 228     // buffers, allocated by ByteBuffer.allocateDirect, to be page aligned.
 229     private static boolean pageAlignDirectMemory;
 230 
 231     // Returns {@code true} if the direct buffers should be page aligned. This
 232     // variable is initialized by saveAndRemoveProperties.
 233     public static boolean isDirectMemoryPageAligned() {
 234         return pageAlignDirectMemory;
 235     }
 236 
 237     /**
 238      * Returns true if the given class loader is in the system domain
 239      * in which all permissions are granted.
 240      */
 241     public static boolean isSystemDomainLoader(ClassLoader loader) {
 242         return loader == null;
 243     }
 244 
 245     /**
 246      * Returns the system property of the specified key saved at
 247      * system initialization time.  This method should only be used
 248      * for the system properties that are not changed during runtime.
 249      * It accesses a private copy of the system properties so
 250      * that user's locking of the system properties object will not
 251      * cause the library to deadlock.
 252      *
 253      * Note that the saved system properties do not include
 254      * the ones set by sun.misc.Version.init().
 255      *
 256      */
 257     public static String getSavedProperty(String key) {
 258         if (savedProps.isEmpty())
 259             throw new IllegalStateException("Should be non-empty if initialized");
 260 
 261         return savedProps.getProperty(key);
 262     }
 263 
 264     // TODO: the Property Management needs to be refactored and
 265     // the appropriate prop keys need to be accessible to the
 266     // calling classes to avoid duplication of keys.
 267     private static final Properties savedProps = new Properties();
 268 
 269     // Save a private copy of the system properties and remove
 270     // the system properties that are not intended for public access.
 271     //
 272     // This method can only be invoked during system initialization.
 273     public static void saveAndRemoveProperties(Properties props) {
 274         if (initLevel() != 0)
 275             throw new IllegalStateException("Wrong init level");
 276 
 277         savedProps.putAll(props);
 278 
 279         // Set the maximum amount of direct memory.  This value is controlled
 280         // by the vm option -XX:MaxDirectMemorySize=<size>.
 281         // The maximum amount of allocatable direct buffer memory (in bytes)
 282         // from the system property sun.nio.MaxDirectMemorySize set by the VM.
 283         // The system property will be removed.
 284         String s = (String)props.remove("sun.nio.MaxDirectMemorySize");
 285         if (s != null) {
 286             if (s.equals("-1")) {
 287                 // -XX:MaxDirectMemorySize not given, take default
 288                 directMemory = Runtime.getRuntime().maxMemory();
 289             } else {
 290                 long l = Long.parseLong(s);
 291                 if (l > -1)
 292                     directMemory = l;
 293             }
 294         }
 295 
 296         // Check if direct buffers should be page aligned
 297         s = (String)props.remove("sun.nio.PageAlignDirectMemory");
 298         if ("true".equals(s))
 299             pageAlignDirectMemory = true;
 300 
 301         // Remove other private system properties
 302         // used by java.lang.Integer.IntegerCache
 303         props.remove("java.lang.Integer.IntegerCache.high");
 304 
 305         // used by sun.launcher.LauncherHelper
 306         props.remove("sun.java.launcher.diag");
 307 
 308         // used by jdk.internal.loader.ClassLoaders
 309         props.remove("jdk.boot.class.path.append");
 310     }
 311 
 312     // Initialize any miscellaneous operating system settings that need to be
 313     // set for the class libraries.
 314     //
 315     public static void initializeOSEnvironment() {
 316         if (initLevel() == 0) {
 317             OSEnvironment.initialize();
 318         }
 319     }
 320 
 321     /* Current count of objects pending for finalization */
 322     private static volatile int finalRefCount;
 323 
 324     /* Peak count of objects pending for finalization */
 325     private static volatile int peakFinalRefCount;
 326 
 327     /*
 328      * Gets the number of objects pending for finalization.
 329      *
 330      * @return the number of objects pending for finalization.
 331      */
 332     public static int getFinalRefCount() {
 333         return finalRefCount;
 334     }
 335 
 336     /*
 337      * Gets the peak number of objects pending for finalization.
 338      *
 339      * @return the peak number of objects pending for finalization.
 340      */
 341     public static int getPeakFinalRefCount() {
 342         return peakFinalRefCount;
 343     }
 344 
 345     /*
 346      * Add {@code n} to the objects pending for finalization count.
 347      *
 348      * @param n an integer value to be added to the objects pending
 349      * for finalization count
 350      */
 351     public static void addFinalRefCount(int n) {
 352         // The caller must hold lock to synchronize the update.
 353 
 354         finalRefCount += n;
 355         if (finalRefCount > peakFinalRefCount) {
 356             peakFinalRefCount = finalRefCount;
 357         }
 358     }
 359 
 360     /**
 361      * Returns Thread.State for the given threadStatus
 362      */
 363     public static Thread.State toThreadState(int threadStatus) {
 364         if ((threadStatus & JVMTI_THREAD_STATE_RUNNABLE) != 0) {
 365             return RUNNABLE;
 366         } else if ((threadStatus & JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER) != 0) {
 367             return BLOCKED;
 368         } else if ((threadStatus & JVMTI_THREAD_STATE_WAITING_INDEFINITELY) != 0) {
 369             return WAITING;
 370         } else if ((threadStatus & JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT) != 0) {
 371             return TIMED_WAITING;
 372         } else if ((threadStatus & JVMTI_THREAD_STATE_TERMINATED) != 0) {
 373             return TERMINATED;
 374         } else if ((threadStatus & JVMTI_THREAD_STATE_ALIVE) == 0) {
 375             return NEW;
 376         } else {
 377             return RUNNABLE;
 378         }
 379     }
 380 
 381     /* The threadStatus field is set by the VM at state transition
 382      * in the hotspot implementation. Its value is set according to
 383      * the JVM TI specification GetThreadState function.
 384      */
 385     private static final int JVMTI_THREAD_STATE_ALIVE = 0x0001;
 386     private static final int JVMTI_THREAD_STATE_TERMINATED = 0x0002;
 387     private static final int JVMTI_THREAD_STATE_RUNNABLE = 0x0004;
 388     private static final int JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400;
 389     private static final int JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010;
 390     private static final int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020;
 391 
 392     /*
 393      * Returns the first non-null class loader up the execution stack,
 394      * or null if only code from the null class loader is on the stack.
 395      */
 396     public static native ClassLoader latestUserDefinedLoader();
 397 
 398     /**
 399      * Returns {@code true} if we are in a set UID program.
 400      */
 401     public static boolean isSetUID() {
 402         long uid = getuid();
 403         long euid = geteuid();
 404         long gid = getgid();
 405         long egid = getegid();
 406         return uid != euid  || gid != egid;
 407     }
 408 
 409     /**
 410      * Returns the real user ID of the calling process,
 411      * or -1 if the value is not available.
 412      */
 413     public static native long getuid();
 414 
 415     /**
 416      * Returns the effective user ID of the calling process,
 417      * or -1 if the value is not available.
 418      */
 419     public static native long geteuid();
 420 
 421     /**
 422      * Returns the real group ID of the calling process,
 423      * or -1 if the value is not available.
 424      */
 425     public static native long getgid();
 426 
 427     /**
 428      * Returns the effective group ID of the calling process,
 429      * or -1 if the value is not available.
 430      */
 431     public static native long getegid();
 432 
 433     /**
 434      * Get a nanosecond time stamp adjustment in the form of a single long.
 435      *
 436      * This value can be used to create an instant using
 437      * {@link java.time.Instant#ofEpochSecond(long, long)
 438      *  java.time.Instant.ofEpochSecond(offsetInSeconds,
 439      *  getNanoTimeAdjustment(offsetInSeconds))}.
 440      * <p>
 441      * The value returned has the best resolution available to the JVM on
 442      * the current system.
 443      * This is usually down to microseconds - or tenth of microseconds -
 444      * depending on the OS/Hardware and the JVM implementation.
 445      *
 446      * @param offsetInSeconds The offset in seconds from which the nanosecond
 447      *        time stamp should be computed.
 448      *
 449      * @apiNote The offset should be recent enough - so that
 450      *         {@code offsetInSeconds} is within {@code +/- 2^32} seconds of the
 451      *         current UTC time. If the offset is too far off, {@code -1} will be
 452      *         returned. As such, {@code -1} must not be considered as a valid
 453      *         nano time adjustment, but as an exception value indicating
 454      *         that an offset closer to the current time should be used.
 455      *
 456      * @return A nanosecond time stamp adjustment in the form of a single long.
 457      *     If the offset is too far off the current time, this method returns -1.
 458      *     In that case, the caller should call this method again, passing a
 459      *     more accurate offset.
 460      */
 461     public static native long getNanoTimeAdjustment(long offsetInSeconds);
 462 
 463     static {
 464         initialize();
 465     }
 466     private static native void initialize();
 467 }