OutOfMemoryError异常 (笔记)

简述:

《深入理解Java虚拟机》一书第2张阅读笔记


1. Java堆溢出

jvm启动参数设置

-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8

-Xms和-Xmx参数设置一样可以避免堆自动扩展

-XX:+HeapDumpOnOutOfMemoryError 可以让虚拟机在出现内存溢出异常时,Dump出当前的内存堆转储快照一边时候进行分析

-Xmn10M 设置年轻代的大小为10M

-XX:SurvivorRatio 设置年轻代中Eden区和单个survivor区的配置比为8

要保证GC roots到对象之间有可达路径来避免垃圾回收机制清除这些对象

(书上可能有一处问题,不能用ArrayList,由于其在扩容时候会执行Array.copy方法,导致在add之前,先发生array申请memeory的报错)

所以此处用LinkedList代替。

package com.anialy.test.jvm.outofmemeoryerror;

import java.util.LinkedList;
import java.util.List;

/**
 * 堆溢出
 */
public class HeapOOM {
	public static void main(String[] args) {
		List<HeapOOM> list = new LinkedList<HeapOOM>();
		while(true){
			list.add(new HeapOOM());
		}
	}
}
 

报错如下,




2. 栈溢出

package com.anialy.test.jvm.outofmemeoryerror;

/**
 * 栈溢出 
 */
public class StackSOF {
	private static int stackHeight = 0;
	
	public static void stackLeak(){
		StackSOF.stackHeight++;
		System.out.printf("stack height:  %d\n", stackHeight);
		stackLeak();
	}
	
	public static void main(String[] args) {
		try{
			stackLeak();
		}catch(Exception e){
			System.out.printf("stack height:  %d\n", stackHeight);
		}
	}
}


输出:


增大线程堆栈高度的方式,

1) 减少最大堆容量 -Xmx ,由于内存主要是由Xmx最大堆容量和MaxPermSize最大方法区容量占用的

剩余的内存空间只留给了虚拟机栈和本地方法栈

2)增大栈容量 -Xss100M (不合理 只是作测试)

这时候发现堆栈可达高度变大了




3. 运行时常量池溢出

启动参数:

-Xms20M -Xmx20M -Xmn10M

ConstantPoolOOM.java

package com.anialy.test.jvm.outofmemeoryerror;

import java.util.LinkedList;
import java.util.List;

/**
 * 运行时常量池溢出
 */
public class ConstantPoolOOM {
	public static void main(String[] args) {
		List<String> list = new LinkedList<String>();
		int i = 0;
		while(true){
			list.add(String.valueOf(i++));
		}
	}
}

报错输出:




4. 方法区溢出

package com.anialy.test.jvm.outofmemeoryerror;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 * 方法区溢出
 * 需要使用Cglib进行对类的字节码增强
 */
public class MethodAreaOOM {
	public static void main(String[] args) {
		while(true){
			Enhancer enhancer = new Enhancer();
			enhancer.setSuperclass(MethodAreaOOM.class);
			enhancer.setUseCache(false);
			enhancer.setCallback(new MethodInterceptor() {
				public Object intercept(Object obj, Method method, Object[] args,
						MethodProxy proxy) throws Throwable {
					return proxy.invokeSuper(obj, args);
				}
			});
			enhancer.create();
		}
	}
}


5.直接内存Direct Memory溢出

直接设置DirectMemory大小

-XX:MaxDirectMemorySize=128m

DirectMemoryOOM

package com.anialy.test.jvm.outofmemeoryerror;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import sun.misc.Unsafe;

import org.springframework.objenesis.instantiator.sun.UnsafeFactoryInstantiator;

/**
 * 直接内存 溢出
 */
public class DirectMemoryOOM {
	private static final int _1MB = 1024*1024;
	
	private Unsafe unsafe;
	
	public static void main(String[] args) 
			throws IllegalArgumentException, IllegalAccessException {
		Field unsafeField = Unsafe.class.getDeclaredFields()[0];
		unsafeField.setAccessible(true);
		Unsafe unsafe = (Unsafe) unsafeField.get(null);
		while(true){
			unsafe.allocateMemory(_1MB);
		}
	}
}

输出:






















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值