| /* |
| * Copyright 1996-2005 Sun Microsystems, Inc. All Rights Reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Sun designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Sun in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| * CA 95054 USA or visit www.sun.com if you need additional information or |
| * have any questions. |
| */ |
| |
| package sun.misc; |
| |
| import java.util.Properties; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Set; |
| |
| public class VM { |
| |
| /* The following methods used to be native methods that instruct |
| * the VM to selectively suspend certain threads in low-memory |
| * situations. They are inherently dangerous and not implementable |
| * on native threads. We removed them in JDK 1.2. The skeletons |
| * remain so that existing applications that use these methods |
| * will still work. |
| */ |
| private static boolean suspended = false; |
| |
| /** @deprecated */ |
| @Deprecated |
| public static boolean threadsSuspended() { |
| return suspended; |
| } |
| |
| public static boolean allowThreadSuspension(ThreadGroup g, boolean b) { |
| return g.allowThreadSuspension(b); |
| } |
| |
| /** @deprecated */ |
| @Deprecated |
| public static boolean suspendThreads() { |
| suspended = true; |
| return true; |
| } |
| |
| // Causes any suspended threadgroups to be resumed. |
| /** @deprecated */ |
| @Deprecated |
| public static void unsuspendThreads() { |
| suspended = false; |
| } |
| |
| // Causes threadgroups no longer marked suspendable to be resumed. |
| /** @deprecated */ |
| @Deprecated |
| public static void unsuspendSomeThreads() { |
| } |
| |
| /* Deprecated fields and methods -- Memory advice not supported in 1.2 */ |
| |
| /** @deprecated */ |
| @Deprecated |
| public static final int STATE_GREEN = 1; |
| |
| /** @deprecated */ |
| @Deprecated |
| public static final int STATE_YELLOW = 2; |
| |
| /** @deprecated */ |
| @Deprecated |
| public static final int STATE_RED = 3; |
| |
| /** @deprecated */ |
| @Deprecated |
| public static final int getState() { |
| return STATE_GREEN; |
| } |
| |
| /** @deprecated */ |
| @Deprecated |
| public static void registerVMNotification(VMNotification n) { } |
| |
| /** @deprecated */ |
| @Deprecated |
| public static void asChange(int as_old, int as_new) { } |
| |
| /** @deprecated */ |
| @Deprecated |
| public static void asChange_otherthread(int as_old, int as_new) { } |
| |
| /* |
| * Not supported in 1.2 because these will have to be exported as |
| * JVM functions, and we are not sure we want do that. Leaving |
| * here so it can be easily resurrected -- just remove the // |
| * comments. |
| */ |
| |
| /** |
| * Resume Java profiling. All profiling data is added to any |
| * earlier profiling, unless <code>resetJavaProfiler</code> is |
| * called in between. If profiling was not started from the |
| * command line, <code>resumeJavaProfiler</code> will start it. |
| * <p> |
| * |
| * NOTE: Profiling must be enabled from the command line for a |
| * java.prof report to be automatically generated on exit; if not, |
| * writeJavaProfilerReport must be invoked to write a report. |
| * |
| * @see resetJavaProfiler |
| * @see writeJavaProfilerReport |
| */ |
| |
| // public native static void resumeJavaProfiler(); |
| |
| /** |
| * Suspend Java profiling. |
| */ |
| // public native static void suspendJavaProfiler(); |
| |
| /** |
| * Initialize Java profiling. Any accumulated profiling |
| * information is discarded. |
| */ |
| // public native static void resetJavaProfiler(); |
| |
| /** |
| * Write the current profiling contents to the file "java.prof". |
| * If the file already exists, it will be overwritten. |
| */ |
| // public native static void writeJavaProfilerReport(); |
| |
| |
| private static volatile boolean booted = false; |
| |
| // Invoked by by System.initializeSystemClass just before returning. |
| // Subsystems that are invoked during initialization can check this |
| // property in order to avoid doing things that should wait until the |
| // application class loader has been set up. |
| // |
| public static void booted() { |
| booted = true; |
| } |
| |
| public static boolean isBooted() { |
| return booted; |
| } |
| |
| // A user-settable upper limit on the maximum amount of allocatable direct |
| // buffer memory. This value may be changed during VM initialization if |
| // "java" is launched with "-XX:MaxDirectMemorySize=<size>". |
| // |
| // The initial value of this field is arbitrary; during JRE initialization |
| // it will be reset to the value specified on the command line, if any, |
| // otherwise to Runtime.getRuntime.maxDirectMemory(). |
| // |
| private static long directMemory = 64 * 1024 * 1024; |
| |
| // If this method is invoked during VM initialization, it initializes the |
| // maximum amount of allocatable direct buffer memory (in bytes) from the |
| // system property sun.nio.MaxDirectMemorySize. The system property will |
| // be removed when it is accessed. |
| // |
| // If this method is invoked after the VM is booted, it returns the |
| // maximum amount of allocatable direct buffer memory. |
| // |
| public static long maxDirectMemory() { |
| if (booted) |
| return directMemory; |
| |
| Properties p = System.getProperties(); |
| String s = (String)p.remove("sun.nio.MaxDirectMemorySize"); |
| System.setProperties(p); |
| |
| if (s != null) { |
| if (s.equals("-1")) { |
| // -XX:MaxDirectMemorySize not given, take default |
| directMemory = Runtime.getRuntime().maxMemory(); |
| } else { |
| long l = Long.parseLong(s); |
| if (l > -1) |
| directMemory = l; |
| } |
| } |
| |
| return directMemory; |
| } |
| |
| // A user-settable boolean to determine whether ClassLoader.loadClass should |
| // accept array syntax. This value may be changed during VM initialization |
| // via the system property "sun.lang.ClassLoader.allowArraySyntax". |
| // |
| // The default for 1.5 is "true", array syntax is allowed. In 1.6, the |
| // default will be "false". The presence of this system property to |
| // control array syntax allows applications the ability to preview this new |
| // behaviour. |
| // |
| private static boolean defaultAllowArraySyntax = false; |
| private static boolean allowArraySyntax = defaultAllowArraySyntax; |
| |
| // If this method is invoked during VM initialization, it initializes the |
| // allowArraySyntax boolean based on the value of the system property |
| // "sun.lang.ClassLoader.allowArraySyntax". If the system property is not |
| // provided, the default for 1.5 is "true". In 1.6, the default will be |
| // "false". If the system property is provided, then the value of |
| // allowArraySyntax will be equal to "true" if Boolean.parseBoolean() |
| // returns "true". Otherwise, the field will be set to "false". |
| // |
| // If this method is invoked after the VM is booted, it returns the |
| // allowArraySyntax boolean set during initialization. |
| // |
| public static boolean allowArraySyntax() { |
| if (!booted) { |
| String s |
| = System.getProperty("sun.lang.ClassLoader.allowArraySyntax"); |
| allowArraySyntax = (s == null |
| ? defaultAllowArraySyntax |
| : Boolean.parseBoolean(s)); |
| } |
| return allowArraySyntax; |
| } |
| |
| // Initialize any miscellenous operating system settings that need to be |
| // set for the class libraries. |
| // |
| public static void initializeOSEnvironment() { |
| if (!booted) { |
| OSEnvironment.initialize(); |
| } |
| } |
| |
| /* Current count of objects pending for finalization */ |
| private static volatile int finalRefCount = 0; |
| |
| /* Peak count of objects pending for finalization */ |
| private static volatile int peakFinalRefCount = 0; |
| |
| /* |
| * Gets the number of objects pending for finalization. |
| * |
| * @return the number of objects pending for finalization. |
| */ |
| public static int getFinalRefCount() { |
| return finalRefCount; |
| } |
| |
| /* |
| * Gets the peak number of objects pending for finalization. |
| * |
| * @return the peak number of objects pending for finalization. |
| */ |
| public static int getPeakFinalRefCount() { |
| return peakFinalRefCount; |
| } |
| |
| /* |
| * Add <tt>n</tt> to the objects pending for finalization count. |
| * |
| * @param n an integer value to be added to the objects pending |
| * for finalization count |
| */ |
| public static void addFinalRefCount(int n) { |
| // The caller must hold lock to synchronize the update. |
| |
| finalRefCount += n; |
| if (finalRefCount > peakFinalRefCount) { |
| peakFinalRefCount = finalRefCount; |
| } |
| } |
| |
| |
| public static Thread.State toThreadState(int threadStatus) { |
| // Initialize the threadStateMap |
| initThreadStateMap(); |
| |
| Thread.State s = threadStateMap.get(threadStatus); |
| if (s == null) { |
| // default to RUNNABLE if the threadStatus value is unknown |
| s = Thread.State.RUNNABLE; |
| } |
| return s; |
| } |
| |
| // a map of threadStatus values to the corresponding Thread.State |
| private static Map<Integer, Thread.State> threadStateMap = null; |
| private static Map<Integer, String> threadStateNames = null; |
| |
| private synchronized static void initThreadStateMap() { |
| if (threadStateMap != null) { |
| return; |
| } |
| |
| final Thread.State[] ts = Thread.State.values(); |
| |
| final int[][] vmThreadStateValues = new int[ts.length][]; |
| final String[][] vmThreadStateNames = new String[ts.length][]; |
| getThreadStateValues(vmThreadStateValues, vmThreadStateNames); |
| |
| threadStateMap = new HashMap<Integer, Thread.State>(); |
| threadStateNames = new HashMap<Integer, String>(); |
| for (int i = 0; i < ts.length; i++) { |
| String state = ts[i].name(); |
| int[] values = null; |
| String[] names = null; |
| for (int j = 0; j < ts.length; j++) { |
| if (vmThreadStateNames[j][0].startsWith(state)) { |
| values = vmThreadStateValues[j]; |
| names = vmThreadStateNames[j]; |
| } |
| } |
| if (values == null) { |
| throw new InternalError("No VM thread state mapped to " + |
| state); |
| } |
| if (values.length != names.length) { |
| throw new InternalError("VM thread state values and names " + |
| " mapped to " + state + ": length not matched" ); |
| } |
| for (int k = 0; k < values.length; k++) { |
| threadStateMap.put(values[k], ts[i]); |
| threadStateNames.put(values[k], names[k]); |
| } |
| } |
| } |
| // Fill in vmThreadStateValues with int arrays, each of which contains |
| // the threadStatus values mapping to the Thread.State enum constant. |
| // Fill in vmThreadStateNames with String arrays, each of which contains |
| // the name of each threadStatus value of the format: |
| // <Thread.State.name()>[.<Substate name>] |
| // e.g. WAITING.OBJECT_WAIT |
| // |
| private native static void getThreadStateValues(int[][] vmThreadStateValues, |
| String[][] vmThreadStateNames); |
| |
| static { |
| initialize(); |
| } |
| private native static void initialize(); |
| } |