OutOfMemoryError异常

8 篇文章 0 订阅

1.Java堆溢出

代码如下:

import java.util.ArrayList;
import java.util.List;

/* 
* @author zzf 
* @date 2019年3月6日 下午2:48:03 
*/
public class HeapOOM {
	
	static class OOMObject{}
	
	public static void main(String[] args) {
		List<OOMObject> list=new ArrayList<OOMObject>();
		int i=0;
		while(true){
			System.out.println(i++);
			list.add(new OOMObject());
		}
	}

}

设置Java堆大小为20M(通过设置堆最小值-Xms参数与最大值-Xmx参数设置相同防止堆自动扩展),设置参数-XX:+HeapDumpOnOutOfMemoryError可以让虚拟机在出现内存溢出溢出是Dump当前内存堆转储快照。

-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

分析软件下载地址:http://www.eclipse.org/mat/downloads.php

    Java堆内存的OOM异常时常见的内存溢出异常情况,当出现Java堆内存溢出时,异常堆栈信息“java.lang.OutOfMemoryError”会进一步提示“Java heap space”。

    解决这个异常主要区分时内存泄漏还是内存溢出。如果是内存泄漏可以看泄漏对象到GC Roots的引用链,最后找到为何垃圾收集器无法自动回收。如果不存在泄漏,这意味着对象都存活,这就检查虚拟机的堆参数(-Xmx和-Xms)。

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

    由于在HotSpot虚拟机中不区分虚拟机栈和本地方法栈,所以对于HotSpot来说-Xoss参数(设置本地方法栈大小)是无效的,栈容量只由参数-Xss参数设定。

    它在Java虚拟机规范中描述了两种异常:

  • 如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常。
  • 如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常。

出现 StackOverflowError的方式:

通过-Xss参数减少栈内存。结果:抛出StackOverflowError异常。

定义大量本地变量,增大方法栈中本地变量表的长度。结果:StackOverflowError异常。

/* 
* @author zzf 
* @date 2019年3月6日 下午3:47:21 
*/
public class JavaVmStackSOF {

	private int stackLength;

	public void stackLeak() {
		stackLength++;
		// while(1!=2)
		stackLeak();
	}

	public static void main(String[] args) throws Throwable {
		JavaVmStackSOF oom = new JavaVmStackSOF();
		try {
			oom.stackLeak();
		} catch (Throwable e) {
			System.out.println(oom.stackLength);
			throw e;
			// TODO: handle exception
		}
	}

}
-Xss128k

创建线程导致内存溢出异常:

/* 
* @author zzf 
* @date 2019年3月6日 下午4:12:15 
*/
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) throws Throwable {
		JavaVMStackOOM oom = new JavaVMStackOOM();
		oom.stackLeakByThread();
	}
}

注意这段代码会使系统卡死!!!!!!!亲测

1.8以后去除了方法区,而元空间在本地内存中所以不受-XX:PermSize和-XX:MaxPermSize的限制。

3.元空间内存溢出

import java.lang.reflect.Method;

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

/* 
* @author zzf 
* @date 2019年3月6日 下午5:23:25 
*/
public class JavaMethodAreaOOM {

	static class OOMObject{
	}
	static int i=0;
	public static void main(String[] args) {
		while (true) {
			Enhancer enhancer = new Enhancer();
			enhancer.setSuperclass(OOMObject.class);
			enhancer.setUseCache(false);
			System.out.println(i++);
			enhancer.setCallback(new MethodInterceptor() {
				public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
					return proxy.invoke(obj, args);
				}
			});
			enhancer.create();
		}
	}
}
-XX:MetaspaceSize=1M -XX:MaxMetaspaceSize=100M

元空间大小可以通过-XX:MetaspaceSize=XXM和-XX:MaxMetaspaceSize=XXM设置。

4.直接内存溢出

import java.lang.reflect.Field;

/* 
* @author zzf 
* @date 2019年3月6日 下午4:45:31 
*/
public class RuntimeConstantPoolOOM {
	// -XX:MaxMetaspaceSize=1M -XX:MaxMetaspaceSize=3M
	public static void main(String[] args) {
		int i = 0;
		try {
			Field field = sun.misc.Unsafe.class.getDeclaredFields()[0];
			field.setAccessible(true);
			sun.misc.Unsafe unsafe = (sun.misc.Unsafe) field.get(null);
			while (true) {
				unsafe.allocateMemory(1024 * 1024);
				i++;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			System.out.println("分配次数:" + i);
		}
	}
}
-XX:MaxDirectMemorySize=3M

由DirectMemory导致的内存溢出,其特征就是在Heap Dump文件中不会有明显的异常。

 

参考《深入理解Java虚拟机 JVM高级特性与最佳实践》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值