001: /*
002: * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.management;
027:
028: import java.lang.management.MemoryPoolMXBean;
029:
030: import java.lang.management.MemoryUsage;
031: import java.lang.management.MemoryType;
032: import java.lang.management.MemoryManagerMXBean;
033: import javax.management.openmbean.CompositeData;
034:
035: import static java.lang.management.MemoryNotificationInfo.*;
036:
037: /**
038: * Implementation class for a memory pool.
039: * Standard and committed hotspot-specific metrics if any.
040: *
041: * ManagementFactory.getMemoryPoolMXBeans() returns a list of
042: * instances of this class.
043: */
044: class MemoryPoolImpl implements MemoryPoolMXBean {
045:
046: private final String name;
047: private final boolean isHeap;
048: private final boolean isValid;
049: private final boolean collectionThresholdSupported;
050: private final boolean usageThresholdSupported;
051:
052: private MemoryManagerMXBean[] managers;
053:
054: private long usageThreshold;
055: private long collectionThreshold;
056:
057: private boolean usageSensorRegistered;
058: private boolean gcSensorRegistered;
059: private Sensor usageSensor;
060: private Sensor gcSensor;
061:
062: MemoryPoolImpl(String name, boolean isHeap, long usageThreshold,
063: long gcThreshold) {
064: this .name = name;
065: this .isHeap = isHeap;
066: this .isValid = true;
067: this .managers = null;
068: this .usageThreshold = usageThreshold;
069: this .collectionThreshold = gcThreshold;
070: this .usageThresholdSupported = (usageThreshold >= 0);
071: this .collectionThresholdSupported = (gcThreshold >= 0);
072: this .usageSensor = new PoolSensor(this , name + " usage sensor");
073: this .gcSensor = new CollectionSensor(this , name
074: + " collection sensor");
075: this .usageSensorRegistered = false;
076: this .gcSensorRegistered = false;
077: }
078:
079: public String getName() {
080: return name;
081: }
082:
083: public boolean isValid() {
084: return isValid;
085: }
086:
087: public MemoryType getType() {
088: if (isHeap) {
089: return MemoryType.HEAP;
090: } else {
091: return MemoryType.NON_HEAP;
092: }
093: }
094:
095: public MemoryUsage getUsage() {
096: return getUsage0();
097: }
098:
099: public synchronized MemoryUsage getPeakUsage() {
100: // synchronized since resetPeakUsage may be resetting the peak usage
101: return getPeakUsage0();
102: }
103:
104: public synchronized long getUsageThreshold() {
105: if (!isUsageThresholdSupported()) {
106: throw new UnsupportedOperationException(
107: "Usage threshold is not supported");
108: }
109: return usageThreshold;
110: }
111:
112: public void setUsageThreshold(long newThreshold) {
113: if (!isUsageThresholdSupported()) {
114: throw new UnsupportedOperationException(
115: "Usage threshold is not supported");
116: }
117:
118: ManagementFactory.checkControlAccess();
119:
120: MemoryUsage usage = getUsage0();
121: if (newThreshold < 0) {
122: throw new IllegalArgumentException("Invalid threshold: "
123: + newThreshold);
124: }
125:
126: if (usage.getMax() != -1 && newThreshold > usage.getMax()) {
127: throw new IllegalArgumentException("Invalid threshold: "
128: + newThreshold + " must be <= maxSize."
129: + " Committed = " + usage.getCommitted()
130: + " Max = " + usage.getMax());
131: }
132:
133: synchronized (this ) {
134: if (!usageSensorRegistered) {
135: // pass the sensor to VM to begin monitoring
136: usageSensorRegistered = true;
137: setPoolUsageSensor(usageSensor);
138: }
139: setUsageThreshold0(usageThreshold, newThreshold);
140: this .usageThreshold = newThreshold;
141: }
142: }
143:
144: private synchronized MemoryManagerMXBean[] getMemoryManagers() {
145: if (managers == null) {
146: managers = getMemoryManagers0();
147: }
148: return managers;
149: }
150:
151: public String[] getMemoryManagerNames() {
152: MemoryManagerMXBean[] mgrs = getMemoryManagers();
153:
154: String[] names = new String[mgrs.length];
155: for (int i = 0; i < mgrs.length; i++) {
156: names[i] = mgrs[i].getName();
157: }
158: return names;
159: }
160:
161: public void resetPeakUsage() {
162: ManagementFactory.checkControlAccess();
163:
164: synchronized (this ) {
165: // synchronized since getPeakUsage may be called concurrently
166: resetPeakUsage0();
167: }
168: }
169:
170: public boolean isUsageThresholdExceeded() {
171: if (!isUsageThresholdSupported()) {
172: throw new UnsupportedOperationException(
173: "Usage threshold is not supported");
174: }
175:
176: // return false if usage threshold crossing checking is disabled
177: if (usageThreshold == 0) {
178: return false;
179: }
180:
181: MemoryUsage u = getUsage0();
182: return (u.getUsed() >= usageThreshold || usageSensor.isOn());
183: }
184:
185: public long getUsageThresholdCount() {
186: if (!isUsageThresholdSupported()) {
187: throw new UnsupportedOperationException(
188: "Usage threshold is not supported");
189: }
190:
191: return usageSensor.getCount();
192: }
193:
194: public boolean isUsageThresholdSupported() {
195: return usageThresholdSupported;
196: }
197:
198: public synchronized long getCollectionUsageThreshold() {
199: if (!isCollectionUsageThresholdSupported()) {
200: throw new UnsupportedOperationException(
201: "CollectionUsage threshold is not supported");
202: }
203:
204: return collectionThreshold;
205: }
206:
207: public void setCollectionUsageThreshold(long newThreshold) {
208: if (!isCollectionUsageThresholdSupported()) {
209: throw new UnsupportedOperationException(
210: "CollectionUsage threshold is not supported");
211: }
212:
213: ManagementFactory.checkControlAccess();
214:
215: MemoryUsage usage = getUsage0();
216: if (newThreshold < 0) {
217: throw new IllegalArgumentException("Invalid threshold: "
218: + newThreshold);
219: }
220:
221: if (usage.getMax() != -1 && newThreshold > usage.getMax()) {
222: throw new IllegalArgumentException("Invalid threshold: "
223: + newThreshold + " > max (" + usage.getMax() + ").");
224: }
225:
226: synchronized (this ) {
227: if (!gcSensorRegistered) {
228: // pass the sensor to VM to begin monitoring
229: gcSensorRegistered = true;
230: setPoolCollectionSensor(gcSensor);
231: }
232: setCollectionThreshold0(collectionThreshold, newThreshold);
233: this .collectionThreshold = newThreshold;
234: }
235: }
236:
237: public boolean isCollectionUsageThresholdExceeded() {
238: if (!isCollectionUsageThresholdSupported()) {
239: throw new UnsupportedOperationException(
240: "CollectionUsage threshold is not supported");
241: }
242:
243: // return false if usage threshold crossing checking is disabled
244: if (collectionThreshold == 0) {
245: return false;
246: }
247:
248: MemoryUsage u = getCollectionUsage0();
249: return (gcSensor.isOn() || (u != null && u.getUsed() >= collectionThreshold));
250: }
251:
252: public long getCollectionUsageThresholdCount() {
253: if (!isCollectionUsageThresholdSupported()) {
254: throw new UnsupportedOperationException(
255: "CollectionUsage threshold is not supported");
256: }
257:
258: return gcSensor.getCount();
259: }
260:
261: public MemoryUsage getCollectionUsage() {
262: return getCollectionUsage0();
263: }
264:
265: public boolean isCollectionUsageThresholdSupported() {
266: return collectionThresholdSupported;
267: }
268:
269: // Native VM support
270: private native MemoryUsage getUsage0();
271:
272: private native MemoryUsage getPeakUsage0();
273:
274: private native MemoryUsage getCollectionUsage0();
275:
276: private native void setUsageThreshold0(long current,
277: long newThreshold);
278:
279: private native void setCollectionThreshold0(long current,
280: long newThreshold);
281:
282: private native void resetPeakUsage0();
283:
284: private native MemoryManagerMXBean[] getMemoryManagers0();
285:
286: private native void setPoolUsageSensor(Sensor s);
287:
288: private native void setPoolCollectionSensor(Sensor s);
289:
290: // package private
291:
292: /**
293: * PoolSensor will be triggered by the VM when the memory
294: * usage of a memory pool is crossing the usage threshold.
295: * The VM will not trigger this sensor in subsequent crossing
296: * unless the memory usage has returned below the threshold.
297: */
298: class PoolSensor extends Sensor {
299: MemoryPoolImpl pool;
300:
301: PoolSensor(MemoryPoolImpl pool, String name) {
302: super (name);
303: this .pool = pool;
304: }
305:
306: void triggerAction(MemoryUsage usage) {
307: // create and send notification
308: MemoryImpl.createNotification(MEMORY_THRESHOLD_EXCEEDED,
309: pool.getName(), usage, getCount());
310: }
311:
312: void triggerAction() {
313: // Should not reach here
314: throw new InternalError();
315: }
316:
317: void clearAction() {
318: // do nothing
319: }
320: }
321:
322: /**
323: * CollectionSensor will be triggered and cleared by the VM
324: * when the memory usage of a memory pool after GC is crossing
325: * the collection threshold.
326: * The VM will trigger this sensor in subsequent crossing
327: * regardless if the memory usage has changed siince the previous GC.
328: */
329: class CollectionSensor extends Sensor {
330: MemoryPoolImpl pool;
331:
332: CollectionSensor(MemoryPoolImpl pool, String name) {
333: super (name);
334: this .pool = pool;
335: }
336:
337: void triggerAction(MemoryUsage usage) {
338: MemoryImpl.createNotification(
339: MEMORY_COLLECTION_THRESHOLD_EXCEEDED, pool
340: .getName(), usage, gcSensor.getCount());
341: }
342:
343: void triggerAction() {
344: // Should not reach here
345: throw new InternalError();
346: }
347:
348: void clearAction() {
349: // do nothing
350: }
351: }
352: }
|