《深入理解java虚拟机》读书笔记二 【OutOfMemoryError】

1. java堆溢出

EclipseIDE设置:debugconfiguration-->javaapplication-->class-->VMArguments

-Xms20M -Xmx20M -Xmn10M 

-XX:+PrintGCDetails

/**
 * VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
 *
 */
public class HeapOOM {
	static class OOMObject{
		
	}
	public static void main(String[] args){
		List<OOMObject> list = new ArrayList<OOMObject>();
		while(true){
			list.add(new OOMObject());;
		}
		
	}
}


运行结果:

Exceptioninthread "main" java.lang.OutOfMemoryError: Java heap space

分析:内存泄漏Memory Leak,对象应该被回收却没有

内存溢出Memory Overflow空间不够,通过-Xms设置堆最小值,-Xmx设置堆最大值,缩短对象生命周期和持有时间,减少程序运行期的内存消耗。



2. 虚拟机栈和本地方法栈溢出

-Xss设置栈容量

递归导致StackOverflowError

/**
 * VM Args: -Xss128k
 *
 */
public class JavaVMStackSOF {
	private int stackLength = 1;
	public void stackLeak(){
		stackLength++;
		stackLeak();
	}
	public static void main(String[] args) throws Throwable{
		JavaVMStackSOF oom = new JavaVMStackSOF();
		try{
			oom.stackLeak();
		}catch(Throwable e){
			System.out.println("stack length: "+oom.stackLength);
			throw e;
		}
	}
	
}
运行结果:

stacklength: 2275

Exceptionin thread "main"java.lang.StackOverflowError

   atcom.java.vm.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:10)

分析:

只要单线程,不管是栈帧太大,还是虚拟机栈容量太小都抛出StackOverflowError

创建线程导致OOM

/**
 * VM Args: -Xss2m
 *
 */
public class JavaVMStackOOM {
	private void dontStop(){
		while(true){
			
		}
	}
	public void stackLeakByThread(){
		while(true){
			Thread thread = new Thread(new Runnable(){
				public void run(){
					dontStop();
				}
			});
			thread.start();
		}
	}
	public static void main(String[] args){
		JavaVMStackOOM oom =new JavaVMStackOOM();
		oom.stackLeakByThread();
	}
}
运行结果:

Exceptionin thread "main" java.lang.OutOfMemoryError: unable to create newnative thread

分析:此时的OOM与栈空间的大小无关,减少最大堆和减少栈容量可换取更多线程。

3. 运行时常量池溢出

使用String.intern()这个native方法,向常量池添加内容。该方法的作用,如果池中已经包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象,否则,将此String对象包含的字符串添加到常量池中,并返回此String对象的引用。

/**
 * VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M
 *
 */
public class RuntimeConstantPoolOOM {
	public static void main(String[] args){
		//使用list保持常量池引用,避免Full GC回收常量池行为
		List<String> list = new ArrayList<String>();
		//10MB的PermSize在integer范围内足够产生OOM了
		int i=0;
		while(true){
			list.add(String.valueOf(i++).intern());
		}
	}
}
运行结果:

Exceptionin thread "main" java.lang.OutOfMemoryError: PermGen space

4. 方法区溢出

借助CGLib使得方法区出现内存溢出

/**
 * VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M
 *
 */
public class JavaMethodAreaOOM {
	static class OOMObject{
		
	}
	public static void main(String[] args){
		while(true){
			Enhancer enhancer = new Enhancer();
			enhancer.setSuperclass(OOMObject.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();
		}
	}
}
运行结果:

Caused by:java.lang.OutOfMemoryError: PermGen spac

分析:

在动态生成大量class的应用中,如大量JSP或动态产生JSP的应用,要注意类的回收状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值