347 lines · 11.4 KB · Java
RawDownload
/* * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.management; import java.lang.management.ManagementFactory;import java.lang.management.MemoryPoolMXBean;import java.lang.management.MemoryUsage;import java.lang.management.MemoryType;import java.lang.management.MemoryManagerMXBean;import javax.management.openmbean.CompositeData;import javax.management.ObjectName; import static java.lang.management.MemoryNotificationInfo.*; /** * Implementation class for a memory pool. * Standard and committed hotspot-specific metrics if any. * * ManagementFactory.getMemoryPoolMXBeans() returns a list of * instances of this class. */class MemoryPoolImpl implements MemoryPoolMXBean {     private final String  name;    private final boolean isHeap;    private final boolean isValid;    private final boolean collectionThresholdSupported;    private final boolean usageThresholdSupported;     private MemoryManagerMXBean[] managers;     private long  usageThreshold;    private long  collectionThreshold;     private boolean usageSensorRegistered;    private boolean gcSensorRegistered;    private Sensor  usageSensor;    private Sensor  gcSensor;     MemoryPoolImpl(String name, boolean isHeap, long usageThreshold,                   long gcThreshold) {        this.name = name;        this.isHeap = isHeap;        this.isValid = true;        this.managers = null;        this.usageThreshold = usageThreshold;        this.collectionThreshold = gcThreshold;        this.usageThresholdSupported = (usageThreshold >= 0);        this.collectionThresholdSupported = (gcThreshold >= 0);        this.usageSensor = new PoolSensor(this, name + " usage sensor");        this.gcSensor = new CollectionSensor(this, name + " collection sensor");        this.usageSensorRegistered = false;        this.gcSensorRegistered = false;    }     public String getName() {        return name;    }     public boolean isValid() {        return isValid;    }     public MemoryType getType() {        if (isHeap) {            return MemoryType.HEAP;        } else {            return MemoryType.NON_HEAP;        }    }     public MemoryUsage getUsage() {        return getUsage0();    }     public synchronized MemoryUsage getPeakUsage() {        // synchronized since resetPeakUsage may be resetting the peak usage        return getPeakUsage0();    }     public synchronized long getUsageThreshold() {        if (!isUsageThresholdSupported()) {            throw new UnsupportedOperationException(                "Usage threshold is not supported");        }        return usageThreshold;    }     public void setUsageThreshold(long newThreshold) {        if (!isUsageThresholdSupported()) {            throw new UnsupportedOperationException(                "Usage threshold is not supported");        }         Util.checkControlAccess();         MemoryUsage usage = getUsage0();        if (newThreshold < 0) {            throw new IllegalArgumentException(                "Invalid threshold: " + newThreshold);        }         if (usage.getMax() != -1 && newThreshold > usage.getMax()) {            throw new IllegalArgumentException(                "Invalid threshold: " + newThreshold +                " must be <= maxSize." +                " Committed = " + usage.getCommitted() +                " Max = " + usage.getMax());        }         synchronized (this) {            if (!usageSensorRegistered) {                // pass the sensor to VM to begin monitoring                usageSensorRegistered = true;                setPoolUsageSensor(usageSensor);            }            setUsageThreshold0(usageThreshold, newThreshold);            this.usageThreshold = newThreshold;        }    }     private synchronized MemoryManagerMXBean[] getMemoryManagers() {        if (managers == null) {            managers = getMemoryManagers0();        }        return managers;    }     public String[] getMemoryManagerNames() {        MemoryManagerMXBean[] mgrs = getMemoryManagers();         String[] names = new String[mgrs.length];        for (int i = 0; i < mgrs.length; i++) {            names[i] = mgrs[i].getName();        }        return names;    }     public void resetPeakUsage() {        Util.checkControlAccess();         synchronized (this) {            // synchronized since getPeakUsage may be called concurrently            resetPeakUsage0();        }    }     public boolean isUsageThresholdExceeded() {        if (!isUsageThresholdSupported()) {            throw new UnsupportedOperationException(                "Usage threshold is not supported");        }         // return false if usage threshold crossing checking is disabled        if (usageThreshold == 0) {            return false;        }         MemoryUsage u = getUsage0();        return (u.getUsed() >= usageThreshold ||                usageSensor.isOn());    }     public long getUsageThresholdCount() {        if (!isUsageThresholdSupported()) {            throw new UnsupportedOperationException(                "Usage threshold is not supported");        }         return usageSensor.getCount();    }     public boolean isUsageThresholdSupported() {        return usageThresholdSupported;    }     public synchronized long getCollectionUsageThreshold() {        if (!isCollectionUsageThresholdSupported()) {            throw new UnsupportedOperationException(                "CollectionUsage threshold is not supported");        }         return collectionThreshold;    }     public void setCollectionUsageThreshold(long newThreshold) {        if (!isCollectionUsageThresholdSupported()) {            throw new UnsupportedOperationException(                "CollectionUsage threshold is not supported");        }         Util.checkControlAccess();         MemoryUsage usage = getUsage0();        if (newThreshold < 0) {            throw new IllegalArgumentException(                "Invalid threshold: " + newThreshold);        }         if (usage.getMax() != -1 && newThreshold > usage.getMax()) {            throw new IllegalArgumentException(                "Invalid threshold: " + newThreshold +                     " > max (" + usage.getMax() + ").");        }         synchronized (this) {            if (!gcSensorRegistered) {                // pass the sensor to VM to begin monitoring                gcSensorRegistered = true;                setPoolCollectionSensor(gcSensor);            }            setCollectionThreshold0(collectionThreshold, newThreshold);            this.collectionThreshold = newThreshold;        }    }     public boolean isCollectionUsageThresholdExceeded() {        if (!isCollectionUsageThresholdSupported()) {            throw new UnsupportedOperationException(                "CollectionUsage threshold is not supported");        }         // return false if usage threshold crossing checking is disabled        if (collectionThreshold == 0) {            return false;        }         MemoryUsage u = getCollectionUsage0();        return (gcSensor.isOn() ||                (u != null && u.getUsed() >= collectionThreshold));    }     public long getCollectionUsageThresholdCount() {        if (!isCollectionUsageThresholdSupported()) {            throw new UnsupportedOperationException(                "CollectionUsage threshold is not supported");        }         return gcSensor.getCount();    }     public MemoryUsage getCollectionUsage() {        return getCollectionUsage0();    }     public boolean isCollectionUsageThresholdSupported() {        return collectionThresholdSupported;    }     // Native VM support    private native MemoryUsage getUsage0();    private native MemoryUsage getPeakUsage0();    private native MemoryUsage getCollectionUsage0();    private native void setUsageThreshold0(long current, long newThreshold);    private native void setCollectionThreshold0(long current, long newThreshold);    private native void resetPeakUsage0();    private native MemoryManagerMXBean[] getMemoryManagers0();    private native void setPoolUsageSensor(Sensor s);    private native void setPoolCollectionSensor(Sensor s);     // package private     /**     * PoolSensor will be triggered by the VM when the memory     * usage of a memory pool is crossing the usage threshold.     * The VM will not trigger this sensor in subsequent crossing     * unless the memory usage has returned below the threshold.     */    class PoolSensor extends Sensor {        MemoryPoolImpl pool;         PoolSensor(MemoryPoolImpl pool, String name) {            super(name);            this.pool = pool;        }        void triggerAction(MemoryUsage usage) {            // create and send notification            MemoryImpl.createNotification(MEMORY_THRESHOLD_EXCEEDED,                                          pool.getName(),                                          usage,                                          getCount());        }        void triggerAction() {            // Should not reach here            throw new AssertionError("Should not reach here");        }        void clearAction() {            // do nothing        }    }     /**     * CollectionSensor will be triggered and cleared by the VM     * when the memory usage of a memory pool after GC is crossing     * the collection threshold.     * The VM will trigger this sensor in subsequent crossing     * regardless if the memory usage has changed siince the previous GC.     */    class CollectionSensor extends Sensor {        MemoryPoolImpl pool;        CollectionSensor(MemoryPoolImpl pool, String name) {            super(name);            this.pool = pool;        }        void triggerAction(MemoryUsage usage) {            MemoryImpl.createNotification(MEMORY_COLLECTION_THRESHOLD_EXCEEDED,                                          pool.getName(),                                          usage,                                          gcSensor.getCount());        }        void triggerAction() {            // Should not reach here            throw new AssertionError("Should not reach here");        }        void clearAction() {            // do nothing        }    }     public ObjectName getObjectName() {        return Util.newObjectName(ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE, getName());    } }