001: /*
002: * @(#)VM.java 1.21 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package sun.misc;
029:
030: import java.util.Vector;
031:
032: /**
033: * The Sun.misc.vm class provides an interface to the memory
034: * management system of the Virtual Machine so that applications
035: * and applets can be informed of the state of memory system.
036: * Memory States :
037: * <li>Green
038: * When the memory state is "Green", the vm has sufficient memory
039: * to run normally.
040: * <li>Yellow
041: * When the memory state is "Yellow", the vm still has sufficient
042: * memory to run, but large allocations may fail, so an application
043: * may wish to free unnecessary resources or make other space saving trade-offs.
044: * <li>Red
045: * When the memory state is Red, the vm is critically low on memory.
046: * All unnecessary memory should be freed and unnecessary applications should exit.
047: * <p>
048: * These states are represented with the constants
049: * <code>VM.STATE_GREEN, VM.STATE_YELLOW, and VM.STATE_RED.</code>
050: * <h3>Compatibility</h3>
051: * Some PersonalJava implementations support the Sun.misc.vm class.
052: * It is not supported in the J2SE.
053: */
054: public class VM implements Runnable {
055: public static final int STATE_GREEN = 1;
056: public static final int STATE_YELLOW = 2;
057: public static final int STATE_RED = 3;
058: private byte memoryAdvice = STATE_GREEN; // Updated by GC
059: private Object memoryAdviceLock = new Object();
060: private Vector callbacks = new Vector(1);
061: private Object[] callbacksCopy = new Object[1];
062: private Thread callbackThread;
063: private static VM singleton = null;
064:
065: /**
066: * Compute the current memory state. This may be an expensive operation,
067: * because a GC might be triggered to produce an accurate result.
068: * @return the current memory state
069: *
070: */
071: // public static final native int getState();
072: /**
073: * Report the (approximate) memory state at the end of the last GC. This will
074: * be a quick operation that should give a useful approximation of the
075: * real state of the system.
076: *
077: * @return the current memory state
078: */
079: public static final int getStateQuick() {
080: return getSingleton().memoryAdvice;
081: }
082:
083: /**
084: * Register a notifier to be informed when availability of
085: * memory in the system changes state.
086: * <p>
087: * After calling the <code>registerVMNotification()</code> method, the
088: * notifier will be invoked when the specified changes in memory state occur.
089: * @see sun.misc.VMNotification
090: */
091: public static void registerVMNotification(VMNotification n) {
092: getSingleton().registerCallback(n);
093: }
094:
095: //
096: // Don't let anyone else instantiate this class
097: //
098: private VM() {// registerWithGC();
099: }
100:
101: private static VM getSingleton() {
102: if (singleton == null) {
103: createSingleton();
104: }
105: return singleton;
106: }
107:
108: private static synchronized void createSingleton() {
109: if (singleton == null) { // We must re-test this within synchronized
110: singleton = new VM();
111: }
112: }
113:
114: // private native void registerWithGC();
115:
116: private void registerCallback(VMNotification n) {
117: synchronized (this ) {
118: if (callbackThread == null) {
119: callbackThread = new Thread(singleton,
120: "RYG Callback Thread");
121: callbackThread.setPriority(Thread.MAX_PRIORITY - 1);
122: callbackThread.start();
123: }
124: // we update callbacksCopy first in case the memory allocation
125: // triggers a state change. The gc will attempt to acquire
126: // the lock that we already own, which is ok since it's
127: // only going to update fields we're not playing with.
128: synchronized (callbacks) {
129: if (callbacks.size() + 1 > callbacksCopy.length) {
130: callbacksCopy = new Object[callbacks.size() + 1];
131: }
132: callbacks.addElement(n);
133: }
134: }
135: }
136:
137: /**
138: * User code is not meant to call this.
139: */
140: // It's public because that's a requirement of runnable. This isn't
141: // a security hole, because untrusted code can't call into sun.*.
142: public void run() {
143: int previousState = STATE_GREEN;
144: int currentState;
145: while (true) {
146: try {
147: while (true) {
148: synchronized (memoryAdviceLock) {
149: currentState = memoryAdvice;
150: if (currentState != previousState) {
151: break;
152: }
153: memoryAdviceLock.wait();
154: }
155: }
156: // We go to some effort to avoid doing callbacks while holding
157: // locks. Doing otherwise is just asking for trouble.
158: int copySize;
159: Object[] cbc;
160: synchronized (callbacks) {
161: // guaranteed to fit by registerCallback
162: callbacks.copyInto(callbacksCopy);
163: copySize = callbacks.size();
164: // callbacksCopy (the variable, not the object)
165: // may get stored into from registerCallback, so
166: // make a copy of the reference.
167: cbc = callbacksCopy;
168: }
169: // do the callbacks outside of the synchronized block to
170: // avoid locking problems
171: for (int i = 0; i < copySize; i++) {
172: VMNotification n = (VMNotification) cbc[i];
173: try {
174: n.newAllocState(previousState, currentState,
175: true);
176: } catch (Throwable t) {
177: try {
178: t.printStackTrace();
179: } catch (Throwable ignored) {
180: }
181: }
182: }
183: previousState = currentState;
184: } catch (Throwable t) {
185: try {
186: // don't let the RYG Callback thread exit for any reason.
187: t.printStackTrace();
188: } catch (Throwable e) {
189: }
190: }
191: }
192: }
193: }
|