MemoryMXBean和MemoryPoolMXBean--OutOfMemoryError Warning System

MemoryMXBean可以通过ManagementFactory.getMemoryMXBean()获取,也可以通过平台MBeanServer的ObjectName为java.lang:type=Memory获取

MemoryPoolMXBean可以通过ManagementFactory.getMemoryPoolMXBean()获取,也可以通过平台MBeanServer的ObjectName为java.lang:type=MemoryPool,name={pool‘s name}获取

MemoryMXBean的实现MemoryImpl是一个NotificationEmitter类的子类,可以通过addNotificationListener来添加监控;可以监控到MemoryNotificationInfo中定义的两种通知(MEMORY_THRESHOLD_EXCEDED和MEMORY_COLLECTION_THRESHOLD_EXCEEDED,二者区别是是否对不使用的对象经过回收)。

MemoryPoolMXBean可以检测到堆和非堆内存的所有信息,可以清楚的看到Code Cache、Eden Space、Survivor Space、Tenured Gen、Perm Gen等虚拟机内存的信息,通过getUsage()和getPeakUsage()获取信息,通过轮询和通知的方式对阈值进行监控。

注意,我在eclipse中对MemoryMXBean.addNotificationListener中添加的NotificationListener的handleNotification方法设置断点,并未起效,原因可能是Low Memory Detector不支持Java Debug协议,eclipse无法在上面设置断点造成的。

OOME预防可以通过上述工具完成。

首先设置VM arguments Xmx和Xms

代码如下

import javax.management.*;
import java.lang.management.*;
import java.util.*;

/**
 * This memory warning system will call the listener when we
 * exceed the percentage of available memory specified.  There
 * should only be one instance of this object created, since the
 * usage threshold can only be set to one number.
 */
public class MemoryWarningSystem {
  private final Collection<Listener> listeners =
      new ArrayList<Listener>();

  public interface Listener {
    public void memoryUsageLow(long usedMemory, long maxMemory);
  }

  public MemoryWarningSystem() {
    MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();
    NotificationEmitter emitter = (NotificationEmitter) mbean;
    emitter.addNotificationListener(new NotificationListener() {
      public void handleNotification(Notification n, Object hb) {
        if (n.getType().equals(
            MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED)) {
          long maxMemory = tenuredGenPool.getUsage().getMax();
          long usedMemory = tenuredGenPool.getUsage().getUsed();
          for (Listener listener : listeners) {
            listener.memoryUsageLow(usedMemory, maxMemory);
          }
        }
      }
    }, null, null);
  }

  public boolean addListener(Listener listener) {
    return listeners.add(listener);
  }

  public boolean removeListener(Listener listener) {
    return listeners.remove(listener);
  }

  private static final MemoryPoolMXBean tenuredGenPool =
      findTenuredGenPool();

  public static void setPercentageUsageThreshold(double percentage) {
    if (percentage <= 0.0 || percentage > 1.0) {
      throw new IllegalArgumentException("Percentage not in range");
    }
    long maxMemory = tenuredGenPool.getUsage().getMax();
    long warningThreshold = (long) (maxMemory * percentage);
    tenuredGenPool.setUsageThreshold(warningThreshold);
  }

  /**
   * Tenured Space Pool can be determined by it being of type
   * HEAP and by it being possible to set the usage threshold.
   */
  private static MemoryPoolMXBean findTenuredGenPool() {
    for (MemoryPoolMXBean pool :
        ManagementFactory.getMemoryPoolMXBeans()) {
      // I don't know whether this approach is better, or whether
      // we should rather check for the pool name "Tenured Gen"?
      if (pool.getType() == MemoryType.HEAP &&
          pool.isUsageThresholdSupported()) {
        return pool;
      }
    }
    throw new AssertionError("Could not find tenured space");
  }
}

使用MemTest测试

import java.util.*;

public class MemTest {
  public static void main(String[] args) {
    MemoryWarningSystem.setPercentageUsageThreshold(0.6);

    MemoryWarningSystem mws = new MemoryWarningSystem();
    mws.addListener(new MemoryWarningSystem.Listener() {
      public void memoryUsageLow(long usedMemory, long maxMemory) {
        System.out.println("Memory usage low!!!");
        double percentageUsed = ((double) usedMemory) / maxMemory;
        System.out.println("percentageUsed = " + percentageUsed);
        MemoryWarningSystem.setPercentageUsageThreshold(0.8);
      }
    });

    Collection<Double> numbers = new LinkedList<Double>();
    while (true) {
      numbers.add(Math.random());
    }
  }
}

产生结果如下

Memory usage low!!!
percentageUsed = 0.6281726667795322
Memory usage low!!!
percentageUsed = 0.8504659318016649
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

来源:http://www.javaspecialists.co.za/archive/Issue092.html

参考:http://java-boy.iteye.com/blog/464953

MemoryMXBean和MemoryPoolMXBean--OutOfMemoryError Warning System,布布扣,bubuko.com

时间: 2024-09-30 09:28:14

MemoryMXBean和MemoryPoolMXBean--OutOfMemoryError Warning System的相关文章

BUG搬运工:CSCvp31778-3802 apsw_watchdog: WARNING: System memory is running low

如下bug主要针对Cisco COS AP比如18.28.38... 主要现象: AP上连关联的终端显示的是信号满格,但是无法访问内网,所有的终端都这样,只有重启AP后才可以解决. 频率: 这种现象有时候不定期,有时候好多天都不会发生,频率不高. 具体BUG: 3802 apsw_watchdog: WARNING: System memory is running low CSCvp31778 Description Symptom:Clients on RUN state and with

JMX

一.为什么使用JMX,解决那些问题 举一个应用实例:在一个系统中常常会有一些配置信息,比如服务的IP地址,端口号什么的,那么如何来写这些代码呢? 写死在程序里,到要改变时就去改程序,然后再编译发布: 把这些信息写在一个配置文件里(JAVA一般都是*.properties文件),到要改变时只要改配置文件,但还是重新启动系统,以便读取配置文件里的新值: 写一个段代码,把配置值缓存起来,系统在读值的时候,先看看配置文件有没有更动.如有更改则重读一遍,否则从缓存里读取值 用JMX!把配置属性集中在一个类

JVM Management API

JVM本身提供了一组管理的API,通过该API,我们可以获取得到JVM内部主要运行信息,包括内存各代的数据.JVM当前所有线程及其栈相关信 息等等.各种JDK自带的剖析工具,包括jps.jstack.jinfo.jstat.jmap.jconsole等,都是基于此API开发的.本篇对 这部分内容进行一个详细的说明. 参考:http://java.sun.com/javase/6/docs/api/java/lang/management/package-summary.html 一.Manage

Java SE 6 新特性: JMX 与系统管理

Java SE 6 新特性: JMX 与系统管理 2006 年底,Sun 公司发布了 Java Standard Edition 6(Java SE 6)的最终正式版,代号 Mustang(野马).跟 Tiger(Java SE 5)相比,Mustang 在性能方面有了不错的提升.与 Tiger 在 API 库方面的大幅度加强相比,虽然 Mustang 在 API 库方面的新特性显得不太多,但是也提供了许多实用和方便的功能:在脚本,WebService,XML,编译器 API,数据库,JMX,网

LibSVM在Java中的简单应用

首先,在这里首先感谢台湾林智仁先生的开源工具包libsvm.使SVM算法更加普及.大家可以到下面的libsvm官网去了解相关的信息. Libsvm官方网站->https://www.csie.ntu.edu.tw/~cjlin/libsvm/ 其次,我在使用过程中发现,先生svm_scale文件中无法将经过规约的文件输出到本地txt文件中,只能在控制台重定向,而我并不想在程序运行中打开控制台进行较为繁琐的操作. 所以我改造了svm_scale文件,实现了文件的写入,在这里可以和大家分享一下. 改

深入JDK源码,这里总有你不知道的知识点!

Java的基础知识有很多,但是我认为最基础的知识应该要属jdk的基础代码,jdk的基础代码里面,有分了很多基础模块,其中又属jdk包下面的lang包最为基础. 我们下面将总结和分析一下lang包下面最为基础和常用的几个部分. 1:常用的对象类型包 (1)其中最基础的类为Object,所有的对象都是继承于这个类的.我们知道所有的类如果没有显示的声明继承于哪个类的话,默认都会继承于Object类,这个类里面也有很多我们常用的方法的默认实现. (2)然后就是字符串类了,我们常用的有String.Str

JDK核心源码(2)

Java的基础知识有很多,但是我认为最基础的知识应该要属jdk的基础代码, jdk的基础代码里面,有分了很多基础模块,其中又属jdk包下面的lang包最为基础. 我们下面将总结和分析一下lang包下面最为基础和常用的几个部分. 1:常用的对象类型包 (1)其中最基础的类为Object,所有的对象都是继承于这个类的.我们知道所有的类如果没有显示的声明继承于哪个类的话,默认都会继承于Object类,这个类里面也有很多我们常用的方法的默认实现. (2)然后就是字符串类了,我们常用的有String.St

java.lang.management

java.lang.management 提供管理接口,用于监视和管理 Java 虚拟机以及 Java 虚拟机在其上运行的操作系统.它同时允许从本地和远程对正在运行的 Java 虚拟机进行监视和管理. 主要接口: ClassLoadingMXBean  Java虚拟机的类加载系统. CompilationMXBean  Java虚拟机的编译系统. MemoryMXBean  Java虚拟机的内存系统. ThreadMXBean  Java虚拟机的线程系统. RuntimeMXBean  Java

JMX 与系统管理--转

前言 在 Java 程序的运行过程中,对 JVM 和系统的监测一直是 Java 开发人员在开发过程所需要的.一直以来,Java 开发人员必须通过一些底层的 JVM API,比如 JVMPI 和 JVMTI 等,才能监测 Java 程序运行过程中的 JVM 和系统的一系列情况,这种方式一直以来被人所诟病,因为这需要大量的 C 程序和 JNI 调用,开发效率十分低下.于是出现了各种不同的专门做资源管理的程序包.为了解决这个问题,Sun 公司也在其 Java SE 5 版本中,正式提出了 Java 管