src/java.management/share/classes/sun/management/MemoryPoolImpl.java
changeset 47216 71c04702a3d5
parent 45646 285619b3d129
child 49558 b2bd13eafc1c
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     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 
       
    26 package sun.management;
       
    27 
       
    28 import java.lang.management.ManagementFactory;
       
    29 import java.lang.management.MemoryPoolMXBean;
       
    30 import java.lang.management.MemoryUsage;
       
    31 import java.lang.management.MemoryType;
       
    32 import java.lang.management.MemoryManagerMXBean;
       
    33 import javax.management.openmbean.CompositeData;
       
    34 import javax.management.ObjectName;
       
    35 
       
    36 import 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  */
       
    45 class 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 }