Module  java.management
软件包  java.lang.management

Interface MemoryPoolMXBean

  • All Superinterfaces:
    PlatformManagedObject


    public interface MemoryPoolMXBean
    extends PlatformManagedObject
    内存池的管理界面。 内存池代表Java虚拟机管理的内存资源,由一个或多个memory managers管理

    Java虚拟机具有此接口的实现类的一个或多个实例。 实现此接口的实例是一个MXBean ,可以通过调用ManagementFactory.getMemoryPoolMXBeans()方法或从platform MBeanServer方法获得。

    用于唯一标识ObjectName内存池的MXBean的MBeanServer是:

    java.lang:type=MemoryPool ,name= pool's name
    可以通过调用PlatformManagedObject.getObjectName()方法获得。

    内存类型

    Java虚拟机具有用于对象分配的堆,并且还维护方法区域和Java虚拟机执行的非堆内存。 Java虚拟机可以有一个或多个内存池。 每个内存池代表以下类型之一的内存区域:

    内存使用监控

    内存池具有以下属性:

    1. Memory Usage

    getUsage()方法提供了对内存池当前使用情况的估计。 对于垃圾回收的内存池,使用的内存量包括池中所有对象占用的内存,包括可访问不可访问的对象。

    一般来说,这种方法是一个轻量级的操作来获得大致的内存使用。 对于一些内存池,例如,当对象不是连续打包时,该方法可能是一个昂贵的操作,需要一些计算来确定当前的内存使用情况。 在这种情况下,实施应该记录。

    2. Peak Memory Usage

    虚拟机启动或峰值重置后,Java虚拟机维护内存池的高峰内存使用情况。 峰值内存使用量由返回getPeakUsage()方法和复位通过调用resetPeakUsage()方法。

    3. Usage Threshold

    每个内存池都有一个可管理的属性,称为使用阈值 ,具有由Java虚拟机提供的默认值。 默认值取决于平台。 可以通过setUsageThreshold方法设置使用阈值。 如果阈值设置为正值,则在该内存池中启用使用阈值交叉检查。 如果使用阈值设置为零,则禁用此内存池上的使用阈值交叉检查。 可以使用isUsageThresholdSupported()方法来确定是否支持此功能。

    Java虚拟机在其最佳适当时间(通常在垃圾收集时间)的基础上执行基于内存池的使用阈值交叉检查。 每个内存池维护一个usage threshold count ,每当Java虚拟机检测到内存池使用率正在超过阈值时,它将会增加。

    这种可管理的使用阈值属性设计用于以低开销监视内存使用的增长趋势。 某些内存池的使用阈值可能不合适。 例如,一代代垃圾回收器是许多Java虚拟机实现中使用的常见的垃圾收集算法,它根据年龄管理两代或多代隔离对象。 大多数的对象分配在最年轻的一代 (比如一个托儿所记忆库)中。 托儿所内存池被设计为填充并收集托儿所内存池将释放其大部分内存空间,因为它预计主要包含短命的对象,并且大部分在垃圾收集时无法访问。 在这种情况下,更适合于苗圃内存池不支持使用阈值。 另外,如果一个内存池中的对象分配成本非常低(例如,只是原子指针交换),则Java虚拟机可能不支持该内存池的使用阈值,因为将使用率与阈值高于对象分配的成本。

    可以使用pollingthreshold notification机制来监控系统的内存使用情况。

    1. Polling

      通过为所有内存池调用getUsage()方法或支持使用阈值的那些内存池的isUsageThresholdExceeded()方法,应用程序可以持续监控其内存使用情况。 以下是具有专用于任务分发和处理的线程的示例代码。 在每个时间间隔内,它将根据其内存使用情况确定是否应该接收和处理新任务。 如果内存使用量超过其使用阈值,它会将所有未完成的任务重新分配给其他虚拟机,并停止接收新任务,直到内存使用率低于其使用阈值。

        // Assume the usage threshold is supported for this pool.
             // Set the threshold to myThreshold above which no new tasks
             // should be taken.
             pool.setUsageThreshold(myThreshold);
             ....
      
             boolean lowMemory = false;
             while (true) {
                if (pool.isUsageThresholdExceeded()) {
                    // potential low memory, so redistribute tasks to other VMs
                    lowMemory = true;
                    redistributeTasks();
                    // stop receiving new tasks
                    stopReceivingTasks();
                } else {
                    if (lowMemory) {
                        // resume receiving tasks
                        lowMemory = false;
                        resumeReceivingTasks();
                    }
                    // processing outstanding task
                    ...
                }
                // sleep for sometime
                try {
                    Thread.sleep(sometime);
                } catch (InterruptedException e) {
                    ...
                }
             } 

      上述示例不区分从两次迭代之间的存储器使用率保持高于阈值的情况下,存储器使用量暂时降低到使用阈值以下的情况。 可以使用getUsageThresholdCount()方法返回的使用阈值计数来确定两次轮询之间的内存使用情况是否已恢复到阈值以下。

      下面显示另一个例子,如果内存池处于低内存下并且在动作处理时间内忽略内存使用情况的变化,则需要采取一些措施。

        // Assume the usage threshold is supported for this pool.
             // Set the threshold to myThreshold which determines if
             // the application will take some action under low memory condition.
             pool.setUsageThreshold(myThreshold);
      
             int prevCrossingCount = 0;
             while (true) {
                 // A busy loop to detect when the memory usage
                 // has exceeded the threshold.
                 while (!pool.isUsageThresholdExceeded() ||
                        pool.getUsageThresholdCount() == prevCrossingCount) {
                     try {
                         Thread.sleep(sometime)
                     } catch (InterruptException e) {
                         ....
                     }
                 }
      
                 // Do some processing such as check for memory usage
                 // and issue a warning
                 ....
      
                 // Gets the current threshold count. The busy loop will then
                 // ignore any crossing of threshold happens during the processing.
                 prevCrossingCount = pool.getUsageThresholdCount();
             } 

    2. Usage Threshold Notifications

      MemoryMXBean将发出使用阈值通知。 当Java虚拟机检测到内存池的内存使用量达到或超过使用阈值时,虚拟机将触发MemoryMXBean发出usage threshold exceeded notification 超出使用阈值超过通知将不会生成,直到使用率已经低于阈值,然后再次超过它。

      下面是一个实现与上述第一个例子相同逻辑的示例代码,但使用使用阈值通知机制来检测低内存条件而不是轮询。 在该示例代码中,在接收到通知时,通知侦听器通知另一线程以执行实际动作,例如重新分配未完成的任务,停止接收任务或恢复接收任务。 handleNotification方法应设计为执行非常少量的工作并无延迟地返回,以避免导致后续通知的延迟。 耗时的操作应该由单独的线程执行。 通知侦听器可以由多个线程同时调用; 所以侦听器执行的任务应该被正确同步。

        class MyListener implements javax.management.NotificationListener {
                  public void handleNotification(Notification notification, Object handback)  {
                      String notifType = notification.getType();
                      if (notifType.equals(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED)) {
                          // potential low memory, notify another thread
                          // to redistribute outstanding tasks to other VMs
                          // and stop receiving new tasks.
                          lowMemory = true;
                          notifyAnotherThread(lowMemory);
                      }
                  }
             }
      
             // Register MyListener with MemoryMXBean
             MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();
             NotificationEmitter emitter = (NotificationEmitter) mbean;
             MyListener listener = new MyListener();
             emitter.addNotificationListener(listener, null, null);
      
             // Assume this pool supports a usage threshold.
             // Set the threshold to myThreshold above which no new tasks
             // should be taken.
             pool.setUsageThreshold(myThreshold);
      
             // Usage threshold detection is enabled and notification will be
             // handled by MyListener.  Continue for other processing.
             .... 

      不能保证MemoryMXBean何时发出门槛通知,何时通知。 当调用通知侦听器时,内存池的内存使用量可能会超过使用阈值多次。 MemoryNotificationInfo.getCount()方法返回在构建通知时内存使用量超过使用阈值的次数。 可以与getUsageThresholdCount()方法返回的当前使用阈值进行比较,以确定是否发生了这种情况。

    4. Collection Usage Threshold

    集合使用阈值是一个可管理的属性,仅适用于某些垃圾回收的内存池。 在Java虚拟机通过在垃圾回收时间内循环使用内存池中的未使用对象,已经花费了回收内存空间的努力时,收集的停堆内存池中的某些字节数仍将被使用。 回收使用量阈值允许的值,以用于这个号码,使得如果超过了阈值,一个字节被设置collection usage threshold exceeded notification将由发射MemoryMXBean 此外, collection usage threshold count将会增加。

    可以使用isCollectionUsageThresholdSupported()方法来确定是否支持此功能。

    Java虚拟机基于内存池执行收集使用阈值检查。 如果集合使用阈值设置为正值,则启用此检查。 如果集合使用阈值设置为零,则此内存池将禁用此检查。 默认值为零。 Java虚拟机在垃圾收集时执行收集使用阈值检查。

    一些垃圾回收的内存池可能选择不支持收集使用阈值。 例如,内存池仅由连续的并发垃圾回收器管理。 对象可以通过一些线程在此内存池中分配,而未使用的对象同时由并发垃圾回收器进行回收。 除非有明确的垃圾回收时间是检查内存使用的最佳时间,否则不应该支持收集使用率阈值。

    集合使用阈值用于在Java虚拟机花费回收内存空间后,监视内存使用情况。 也可以通过类似于usage threshold描述的轮询和阈值通知机制监视收集使用情况。

    从以下版本开始:
    1.5
    另请参见:
    ManagementFactory.getPlatformMXBeans(Class)JMX Specification.Ways to Access MXBeans
    • 方法详细信息

      • getName

        String getName​()
        返回表示此内存池的名称。
        结果
        这个内存池的名称。
      • getType

        MemoryType getType​()
        返回此内存池的类型。

        MBeanServer访问
        的映射类型MemoryTypeString并且该值是所述的名称MemoryType

        结果
        这个内存池的类型。
      • getUsage

        MemoryUsage getUsage​()
        返回此内存池的内存使用情况的估计。 如果此内存池无效(即不再存在),此方法返回null

        此方法请求Java虚拟机尽力估计此内存池的当前内存使用情况。 对于一些内存池,该方法可能是一个昂贵的操作,需要一些计算来确定估计。 在这种情况下,实施应该记录。

        该方法设计用于监控系统内存使用情况和检测低内存条件。

        MBeanServer访问
        MemoryUsage的映射类型为CompositeData ,其属性如MemoryUsage中所述

        结果
        一个MemoryUsage对象; null如果此池无效。
      • getPeakUsage

        MemoryUsage getPeakUsage​()
        从Java虚拟机启动或从峰值重置以来,返回此内存池的高峰内存使用情况。 如果此内存池无效(即不再存在),此方法返回null

        MBeanServer访问
        MemoryUsage的映射类型为CompositeData ,其属性如MemoryUsage中所述

        结果
        表示峰值内存使用的MemoryUsage对象; null如果此池无效。
      • resetPeakUsage

        void resetPeakUsage​()
        将此内存池的高峰内存使用率统计信息重置为当前内存使用情况。
        异常
        SecurityException - 如果安全管理器存在并且调用者没有ManagementPermission(“控制”)。
      • isValid

        boolean isValid​()
        测试此内存池是否在Java虚拟机中有效。 一旦Java虚拟机将其从内存系统中删除,内存池将变为无效。
        结果
        true如果内存池在正在运行的Java虚拟机中有效; 否则为false
      • getMemoryManagerNames

        String[] getMemoryManagerNames​()
        返回管理此内存池的内存管理器的名称。 每个内存池将由至少一个内存管理器管理。
        结果
        一组 String对象,每个都是管理此内存池的内存管理器的名称。
      • getUsageThreshold

        long getUsageThreshold​()
        以字节为单位返回此内存池的使用阈值。 每个内存池具有平台相关的默认阈值。 可以通过setUsageThreshold方法更改当前使用阈值。
        结果
        该内存池的使用阈值以字节为单位。
        异常
        UnsupportedOperationException - 如果此内存池不支持使用阈值。
        另请参见:
        isUsageThresholdSupported()
      • setUsageThreshold

        void setUsageThreshold​(long threshold)
        如果此内存池支持使用阈值,则将此内存池的阈值设置为给定的threshold值。 如果阈值设置为正值,则在该内存池中启用使用阈值交叉检查。 如果设置为零,则禁用使用阈值交叉检查。
        参数
        threshold - 新的阈值(以字节为单位)。 必须是非负数。
        异常
        IllegalArgumentException - 如果 threshold为负数或大于此内存池的最大内存量(如果已定义)。
        UnsupportedOperationException - 如果此内存池不支持使用阈值。
        SecurityException - 如果安全管理器存在并且调用者没有ManagementPermission(“控制”)。
        另请参见:
        isUsageThresholdSupported()Usage threshold
      • isUsageThresholdExceeded

        boolean isUsageThresholdExceeded​()
        测试此内存池的内存使用情况是否达到或超过其使用阈值。
        结果
        如果该内存池的内存使用量达到或超过阈值, true ; 否则为false
        异常
        UnsupportedOperationException - 如果此内存池不支持使用阈值。
      • getUsageThresholdCount

        long getUsageThresholdCount​()
        返回内存使用量超过使用率阈值的次数。
        结果
        内存使用量超过其使用阈值的次数。
        异常
        UnsupportedOperationException - 如果此内存池不支持使用阈值。
      • isUsageThresholdSupported

        boolean isUsageThresholdSupported​()
        测试此内存池是否支持使用阈值。
        结果
        true如果此内存池支持使用阈值; 否则为false
      • setCollectionUsageThreshold

        void setCollectionUsageThreshold​(long threshold)
        将此内存池的集合使用阈值设置为给定的threshold值。 当此阈值设置为正值时,Java虚拟机将在其在回收此内存池中未使用的对象的努力之后,在其最佳适当时间内检查内存使用情况。

        如果阈值设置为正值,则在此内存池中启用集合使用阈值交叉检查。 如果设置为零,则禁用集合使用阈值交叉检查。

        参数
        threshold - 新的集合使用阈值(以字节为单位)。 必须是非负数。
        异常
        IllegalArgumentException - 如果 threshold为负数或大于此内存池的最大内存量(如果已定义)。
        UnsupportedOperationException - 如果此内存池不支持集合使用阈值。
        SecurityException - 如果安全管理器存在,并且调用者没有ManagementPermission(“控制”)。
        另请参见:
        isCollectionUsageThresholdSupported()Collection usage threshold
      • isCollectionUsageThresholdExceeded

        boolean isCollectionUsageThresholdExceeded​()
        测试Java虚拟机所耗费的最新集合之后的内存池的内存使用情况是否已达到或超过其集合使用率阈值。 该方法不要求Java虚拟机执行除正常自动内存管理之外的任何垃圾收集。
        结果
        true如果此内存池的内存使用量达到或超过最近集合中的集合使用阈值; 否则为false
        异常
        UnsupportedOperationException - 如果此内存池不支持使用阈值。
      • getCollectionUsageThresholdCount

        long getCollectionUsageThresholdCount​()
        返回Java虚拟机检测到内存使用量达到或超过集合使用率阈值的次数。
        结果
        内存使用量达到或超过集合使用率阈值的次数。
        异常
        UnsupportedOperationException - 如果此内存池不支持集合使用阈值。
        另请参见:
        isCollectionUsageThresholdSupported()
      • getCollectionUsage

        MemoryUsage getCollectionUsage​()
        返回Java虚拟机最近花费在回收此内存池中未使用对象的努力后的内存使用情况。 该方法不要求Java虚拟机执行除正常自动内存管理之外的任何垃圾收集。 如果Java虚拟机不支持此方法,则此方法返回null

        MBeanServer访问
        MemoryUsage的映射类型为CompositeData ,其属性在MemoryUsage指定。

        结果
        一个MemoryUsage表示Java虚拟机最近花费在回收未使用对象之后努力的内存池的内存使用情况; null如果不支持此方法。
      • isCollectionUsageThresholdSupported

        boolean isCollectionUsageThresholdSupported​()
        测试此内存池是否支持集合使用阈值。
        结果
        true如果此内存池支持集合使用阈值; 否则为false