1/* 2 * Copyright (c) 2003, 2017, 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 26package sun.management; 27 28import java.lang.management.ManagementFactory; 29import java.lang.management.MemoryPoolMXBean; 30import java.lang.management.MemoryUsage; 31import java.lang.management.MemoryType; 32import java.lang.management.MemoryManagerMXBean; 33import javax.management.openmbean.CompositeData; 34import javax.management.ObjectName; 35 36import static java.lang.management.MemoryNotificationInfo.*; 37 38/** 39 * Implementation class for a memory pool. 40 * Standard and committed hotspot-specific metrics if any. 41 * 42 * ManagementFactory.getMemoryPoolMXBeans() returns a list of 43 * instances of this class. 44 */ 45class MemoryPoolImpl implements MemoryPoolMXBean { 46 47 private final String name; 48 private final boolean isHeap; 49 private final boolean isValid; 50 private final boolean collectionThresholdSupported; 51 private final boolean usageThresholdSupported; 52 53 private MemoryManagerMXBean[] managers; 54 55 private long usageThreshold; 56 private long collectionThreshold; 57 58 private boolean usageSensorRegistered; 59 private boolean gcSensorRegistered; 60 private Sensor usageSensor; 61 private Sensor gcSensor; 62 63 MemoryPoolImpl(String name, boolean isHeap, long usageThreshold, 64 long gcThreshold) { 65 this.name = name; 66 this.isHeap = isHeap; 67 this.isValid = true; 68 this.managers = null; 69 this.usageThreshold = usageThreshold; 70 this.collectionThreshold = gcThreshold; 71 this.usageThresholdSupported = (usageThreshold >= 0); 72 this.collectionThresholdSupported = (gcThreshold >= 0); 73 this.usageSensor = new PoolSensor(this, name + " usage sensor"); 74 this.gcSensor = new CollectionSensor(this, name + " collection sensor"); 75 this.usageSensorRegistered = false; 76 this.gcSensorRegistered = false; 77 } 78 79 public String getName() { 80 return name; 81 } 82 83 public boolean isValid() { 84 return isValid; 85 } 86 87 public MemoryType getType() { 88 if (isHeap) { 89 return MemoryType.HEAP; 90 } else { 91 return MemoryType.NON_HEAP; 92 } 93 } 94 95 public MemoryUsage getUsage() { 96 return getUsage0(); 97 } 98 99 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 Util.checkControlAccess(); 119 120 MemoryUsage usage = getUsage0(); 121 if (newThreshold < 0) { 122 throw new IllegalArgumentException( 123 "Invalid threshold: " + newThreshold); 124 } 125 126 if (usage.getMax() != -1 && newThreshold > usage.getMax()) { 127 throw new IllegalArgumentException( 128 "Invalid threshold: " + newThreshold + 129 " must be <= maxSize." + 130 " Committed = " + usage.getCommitted() + 131 " Max = " + usage.getMax()); 132 } 133 134 synchronized (this) { 135 if (!usageSensorRegistered) { 136 // pass the sensor to VM to begin monitoring 137 usageSensorRegistered = true; 138 setPoolUsageSensor(usageSensor); 139 } 140 setUsageThreshold0(usageThreshold, newThreshold); 141 this.usageThreshold = newThreshold; 142 } 143 } 144 145 private synchronized MemoryManagerMXBean[] getMemoryManagers() { 146 if (managers == null) { 147 managers = getMemoryManagers0(); 148 } 149 return managers; 150 } 151 152 public String[] getMemoryManagerNames() { 153 MemoryManagerMXBean[] mgrs = getMemoryManagers(); 154 155 String[] names = new String[mgrs.length]; 156 for (int i = 0; i < mgrs.length; i++) { 157 names[i] = mgrs[i].getName(); 158 } 159 return names; 160 } 161 162 public void resetPeakUsage() { 163 Util.checkControlAccess(); 164 165 synchronized (this) { 166 // synchronized since getPeakUsage may be called concurrently 167 resetPeakUsage0(); 168 } 169 } 170 171 public boolean isUsageThresholdExceeded() { 172 if (!isUsageThresholdSupported()) { 173 throw new UnsupportedOperationException( 174 "Usage threshold is not supported"); 175 } 176 177 // return false if usage threshold crossing checking is disabled 178 if (usageThreshold == 0) { 179 return false; 180 } 181 182 MemoryUsage u = getUsage0(); 183 return (u.getUsed() >= usageThreshold || 184 usageSensor.isOn()); 185 } 186 187 public long getUsageThresholdCount() { 188 if (!isUsageThresholdSupported()) { 189 throw new UnsupportedOperationException( 190 "Usage threshold is not supported"); 191 } 192 193 return usageSensor.getCount(); 194 } 195 196 public boolean isUsageThresholdSupported() { 197 return usageThresholdSupported; 198 } 199 200 public synchronized long getCollectionUsageThreshold() { 201 if (!isCollectionUsageThresholdSupported()) { 202 throw new UnsupportedOperationException( 203 "CollectionUsage threshold is not supported"); 204 } 205 206 return collectionThreshold; 207 } 208 209 public void setCollectionUsageThreshold(long newThreshold) { 210 if (!isCollectionUsageThresholdSupported()) { 211 throw new UnsupportedOperationException( 212 "CollectionUsage threshold is not supported"); 213 } 214 215 Util.checkControlAccess(); 216 217 MemoryUsage usage = getUsage0(); 218 if (newThreshold < 0) { 219 throw new IllegalArgumentException( 220 "Invalid threshold: " + newThreshold); 221 } 222 223 if (usage.getMax() != -1 && newThreshold > usage.getMax()) { 224 throw new IllegalArgumentException( 225 "Invalid threshold: " + newThreshold + 226 " > max (" + usage.getMax() + ")."); 227 } 228 229 synchronized (this) { 230 if (!gcSensorRegistered) { 231 // pass the sensor to VM to begin monitoring 232 gcSensorRegistered = true; 233 setPoolCollectionSensor(gcSensor); 234 } 235 setCollectionThreshold0(collectionThreshold, newThreshold); 236 this.collectionThreshold = newThreshold; 237 } 238 } 239 240 public boolean isCollectionUsageThresholdExceeded() { 241 if (!isCollectionUsageThresholdSupported()) { 242 throw new UnsupportedOperationException( 243 "CollectionUsage threshold is not supported"); 244 } 245 246 // return false if usage threshold crossing checking is disabled 247 if (collectionThreshold == 0) { 248 return false; 249 } 250 251 MemoryUsage u = getCollectionUsage0(); 252 return (gcSensor.isOn() || 253 (u != null && u.getUsed() >= collectionThreshold)); 254 } 255 256 public long getCollectionUsageThresholdCount() { 257 if (!isCollectionUsageThresholdSupported()) { 258 throw new UnsupportedOperationException( 259 "CollectionUsage threshold is not supported"); 260 } 261 262 return gcSensor.getCount(); 263 } 264 265 public MemoryUsage getCollectionUsage() { 266 return getCollectionUsage0(); 267 } 268 269 public boolean isCollectionUsageThresholdSupported() { 270 return collectionThresholdSupported; 271 } 272 273 // Native VM support 274 private native MemoryUsage getUsage0(); 275 private native MemoryUsage getPeakUsage0(); 276 private native MemoryUsage getCollectionUsage0(); 277 private native void setUsageThreshold0(long current, long newThreshold); 278 private native void setCollectionThreshold0(long current, long newThreshold); 279 private native void resetPeakUsage0(); 280 private native MemoryManagerMXBean[] getMemoryManagers0(); 281 private native void setPoolUsageSensor(Sensor s); 282 private native void setPoolCollectionSensor(Sensor s); 283 284 // package private 285 286 /** 287 * PoolSensor will be triggered by the VM when the memory 288 * usage of a memory pool is crossing the usage threshold. 289 * The VM will not trigger this sensor in subsequent crossing 290 * unless the memory usage has returned below the threshold. 291 */ 292 class PoolSensor extends Sensor { 293 MemoryPoolImpl pool; 294 295 PoolSensor(MemoryPoolImpl pool, String name) { 296 super(name); 297 this.pool = pool; 298 } 299 void triggerAction(MemoryUsage usage) { 300 // create and send notification 301 MemoryImpl.createNotification(MEMORY_THRESHOLD_EXCEEDED, 302 pool.getName(), 303 usage, 304 getCount()); 305 } 306 void triggerAction() { 307 // do nothing 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 // do nothing 335 } 336 void clearAction() { 337 // do nothing 338 } 339 } 340 341 public ObjectName getObjectName() { 342 return Util.newObjectName(ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE, getName()); 343 } 344 345} 346