blob: 152b31d96c67612afbd7d2a543ec13a1745758f2 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2005 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.management;
27
28import java.lang.management.MemoryPoolMXBean;
29
30import java.lang.management.MemoryUsage;
31import java.lang.management.MemoryType;
32import java.lang.management.MemoryManagerMXBean;
33import javax.management.openmbean.CompositeData;
34
35import static java.lang.management.MemoryNotificationInfo.*;
36
37/**
38 * Implementation class for a memory pool.
39 * Standard and committed hotspot-specific metrics if any.
40 *
41 * ManagementFactory.getMemoryPoolMXBeans() returns a list of
42 * instances of this class.
43 */
44class MemoryPoolImpl implements MemoryPoolMXBean {
45
46 private final String name;
47 private final boolean isHeap;
48 private final boolean isValid;
49 private final boolean collectionThresholdSupported;
50 private final boolean usageThresholdSupported;
51
52 private MemoryManagerMXBean[] managers;
53
54 private long usageThreshold;
55 private long collectionThreshold;
56
57 private boolean usageSensorRegistered;
58 private boolean gcSensorRegistered;
59 private Sensor usageSensor;
60 private Sensor gcSensor;
61
62 MemoryPoolImpl(String name, boolean isHeap, long usageThreshold,
63 long gcThreshold) {
64 this.name = name;
65 this.isHeap = isHeap;
66 this.isValid = true;
67 this.managers = null;
68 this.usageThreshold = usageThreshold;
69 this.collectionThreshold = gcThreshold;
70 this.usageThresholdSupported = (usageThreshold >= 0);
71 this.collectionThresholdSupported = (gcThreshold >= 0);
72 this.usageSensor = new PoolSensor(this, name + " usage sensor");
73 this.gcSensor = new CollectionSensor(this, name + " collection sensor");
74 this.usageSensorRegistered = false;
75 this.gcSensorRegistered = false;
76 }
77
78 public String getName() {
79 return name;
80 }
81
82 public boolean isValid() {
83 return isValid;
84 }
85
86 public MemoryType getType() {
87 if (isHeap) {
88 return MemoryType.HEAP;
89 } else {
90 return MemoryType.NON_HEAP;
91 }
92 }
93
94 public MemoryUsage getUsage() {
95 return getUsage0();
96 }
97
98 public synchronized MemoryUsage getPeakUsage() {
99 // synchronized since resetPeakUsage may be resetting the peak usage
100 return getPeakUsage0();
101 }
102
103 public synchronized long getUsageThreshold() {
104 if (!isUsageThresholdSupported()) {
105 throw new UnsupportedOperationException(
106 "Usage threshold is not supported");
107 }
108 return usageThreshold;
109 }
110
111 public void setUsageThreshold(long newThreshold) {
112 if (!isUsageThresholdSupported()) {
113 throw new UnsupportedOperationException(
114 "Usage threshold is not supported");
115 }
116
117 ManagementFactory.checkControlAccess();
118
119 MemoryUsage usage = getUsage0();
120 if (newThreshold < 0) {
121 throw new IllegalArgumentException(
122 "Invalid threshold: " + newThreshold);
123 }
124
125 if (usage.getMax() != -1 && newThreshold > usage.getMax()) {
126 throw new IllegalArgumentException(
127 "Invalid threshold: " + newThreshold +
128 " 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 ||
183 usageSensor.isOn());
184 }
185
186 public long getUsageThresholdCount() {
187 if (!isUsageThresholdSupported()) {
188 throw new UnsupportedOperationException(
189 "Usage threshold is not supported");
190 }
191
192 return usageSensor.getCount();
193 }
194
195 public boolean isUsageThresholdSupported() {
196 return usageThresholdSupported;
197 }
198
199 public synchronized long getCollectionUsageThreshold() {
200 if (!isCollectionUsageThresholdSupported()) {
201 throw new UnsupportedOperationException(
202 "CollectionUsage threshold is not supported");
203 }
204
205 return collectionThreshold;
206 }
207
208 public void setCollectionUsageThreshold(long newThreshold) {
209 if (!isCollectionUsageThresholdSupported()) {
210 throw new UnsupportedOperationException(
211 "CollectionUsage threshold is not supported");
212 }
213
214 ManagementFactory.checkControlAccess();
215
216 MemoryUsage usage = getUsage0();
217 if (newThreshold < 0) {
218 throw new IllegalArgumentException(
219 "Invalid threshold: " + newThreshold);
220 }
221
222 if (usage.getMax() != -1 && newThreshold > usage.getMax()) {
223 throw new IllegalArgumentException(
224 "Invalid threshold: " + newThreshold +
225 " > max (" + usage.getMax() + ").");
226 }
227
228 synchronized (this) {
229 if (!gcSensorRegistered) {
230 // pass the sensor to VM to begin monitoring
231 gcSensorRegistered = true;
232 setPoolCollectionSensor(gcSensor);
233 }
234 setCollectionThreshold0(collectionThreshold, newThreshold);
235 this.collectionThreshold = newThreshold;
236 }
237 }
238
239 public boolean isCollectionUsageThresholdExceeded() {
240 if (!isCollectionUsageThresholdSupported()) {
241 throw new UnsupportedOperationException(
242 "CollectionUsage threshold is not supported");
243 }
244
245 // return false if usage threshold crossing checking is disabled
246 if (collectionThreshold == 0) {
247 return false;
248 }
249
250 MemoryUsage u = getCollectionUsage0();
251 return (gcSensor.isOn() ||
252 (u != null && u.getUsed() >= collectionThreshold));
253 }
254
255 public long getCollectionUsageThresholdCount() {
256 if (!isCollectionUsageThresholdSupported()) {
257 throw new UnsupportedOperationException(
258 "CollectionUsage threshold is not supported");
259 }
260
261 return gcSensor.getCount();
262 }
263
264 public MemoryUsage getCollectionUsage() {
265 return getCollectionUsage0();
266 }
267
268 public boolean isCollectionUsageThresholdSupported() {
269 return collectionThresholdSupported;
270 }
271
272 // Native VM support
273 private native MemoryUsage getUsage0();
274 private native MemoryUsage getPeakUsage0();
275 private native MemoryUsage getCollectionUsage0();
276 private native void setUsageThreshold0(long current, long newThreshold);
277 private native void setCollectionThreshold0(long current, long newThreshold);
278 private native void resetPeakUsage0();
279 private native MemoryManagerMXBean[] getMemoryManagers0();
280 private native void setPoolUsageSensor(Sensor s);
281 private native void setPoolCollectionSensor(Sensor s);
282
283 // package private
284
285 /**
286 * PoolSensor will be triggered by the VM when the memory
287 * usage of a memory pool is crossing the usage threshold.
288 * The VM will not trigger this sensor in subsequent crossing
289 * unless the memory usage has returned below the threshold.
290 */
291 class PoolSensor extends Sensor {
292 MemoryPoolImpl pool;
293
294 PoolSensor(MemoryPoolImpl pool, String name) {
295 super(name);
296 this.pool = pool;
297 }
298 void triggerAction(MemoryUsage usage) {
299 // create and send notification
300 MemoryImpl.createNotification(MEMORY_THRESHOLD_EXCEEDED,
301 pool.getName(),
302 usage,
303 getCount());
304 }
305 void triggerAction() {
306 // Should not reach here
307 throw new InternalError();
308 }
309 void clearAction() {
310 // do nothing
311 }
312 }
313
314 /**
315 * CollectionSensor will be triggered and cleared by the VM
316 * when the memory usage of a memory pool after GC is crossing
317 * the collection threshold.
318 * The VM will trigger this sensor in subsequent crossing
319 * regardless if the memory usage has changed siince the previous GC.
320 */
321 class CollectionSensor extends Sensor {
322 MemoryPoolImpl pool;
323 CollectionSensor(MemoryPoolImpl pool, String name) {
324 super(name);
325 this.pool = pool;
326 }
327 void triggerAction(MemoryUsage usage) {
328 MemoryImpl.createNotification(MEMORY_COLLECTION_THRESHOLD_EXCEEDED,
329 pool.getName(),
330 usage,
331 gcSensor.getCount());
332 }
333 void triggerAction() {
334 // Should not reach here
335 throw new InternalError();
336 }
337 void clearAction() {
338 // do nothing
339 }
340 }
341}