JVM系列之六:堆分析
内存溢出(OOM)的原因
– 在JVM中,有哪些内存区间?
堆
永久区
Java栈
直接内存
– 堆溢出
- public static void main(String args[]){
- ArrayList<byte[]> list=new ArrayList<byte[]>();
- for(int i=0;i<1024;i++){
- list.add(new byte[1024*1024]);
- }
- }
占用大量堆空间,直接溢出
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at geym.jvm.ch8.oom.SimpleHeapOOM.main(SimpleHeapOOM.java:14)
解决方法:增大堆空间,及时释放内存
– 永久区
生成大量的类
- public static void main(String[] args) {
- for(int i=0;i<100000;i++){
- CglibBean bean = new CglibBean("geym.jvm.ch3.perm.bean"+i,new HashMap());
- }
- }
Caused by: java.lang.OutOfMemoryError: PermGen space
解决方法:增大Perm区,允许Class回收
– Java栈溢出
n 这里的栈溢出指,在创建线程的时候,需要为线程分配栈空间,这个栈空间是向操作系统请求的,如果操作系统无法给出足够的空间,就会抛出OOM
示例:
设置JVM参数 :-Xmx1g -Xss1m 内存空间最大值为1G,线程栈大小为1M
- public static class SleepThread implements Runnable{
- public void run(){
- try {
- Thread.sleep(10000000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- public static void main(String args[]){
- for(int i=0;i<1000;i++){
- new Thread(new SleepThread(),"Thread"+i).start();
- System.out.println("Thread"+i+" created");
- }
- }
运行结果:
Exception in thread "main" java.lang.OutOfMemoryError:
unable to create new native thread
解决方法:减少堆内存,减少线程栈大小
使用Visual VM分析堆
– java自带的多功能分析工具,可以用来分析堆Dump
类的柱状图 ,显示对象数量,总大小等:
从类试图切换到实例试图,显示所有的实例:
使用OQL查询:
返回引用了(0,0)这个点的所有对象
Tomcat OOM分析案例
Tomcat 在接收大量请求时发生OOM,获取堆Dump文件,进行分析。
如果是session过多引起OOM
– OOM由于保存session过多引起,可以考虑增加堆大小
– 如果应用允许,缩短session的过期时间,使得session可以及时过期,并回收