论JVM爆炸的几种姿势及自救方法
前言
如今不管是在面试还是在我们的工作中,OOM总是不断的出现在我们的视野中,所以我们有必要去了解一下导致OOM的原因以及一些基本的调整方法,大家可以通过下面的事例来了解一下什么样的代码会导致OOM,帮助我们以后在工作中能够通过异常信息来判断是JVM里面哪个区域出现了问题。
先介绍一下笔者的相关编码环境。
jdk:java version "1.8.0_121"
ide:IntelliJ IDEA 2019.1 (Community Edition)
正文
1、Java堆溢出
Java中的堆存储的都是对象实例,当我们不断的创建对象,而GC的时候又不能回收,当存储的对象大小超过了-Xmx的值,这时候则会出现OutOfMemoryError.[-XX:+HeapDumpOnOutOfMemoryError]参数可以让jvm出现内存溢出的时候dump出内存堆转储快照。
/**
* VM Args: -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError
* @author wangzenghuang
*/
public class HeapOOMDemo {
public static void main(String[] args) {
List<String> stringList = new ArrayList<>();
while(true){
stringList.add("str");
}
}
}
运行结果,发生OOM,并且在我们项目的根目录dump出当前的内存堆快照
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid1376.hprof ...
Heap dump file created [7972183 bytes in 0.047 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:261)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
at java.util.ArrayList.add(ArrayList.java:458)
at HeapOOMDemo.main(HeapOOMDemo.java:12) Process finished with exit code 1
简单解决思路
那么发生这个问题以后我们的解决思路有哪些呢?我们可以利用一些工具(例如Eclipse Memory Analyzer )来分析dump出的文件,一般来说,当生产环境发生OOM,比较常见的一个原因是发生了内存泄漏,用工具可以分析出泄露的对象到GC Root的引用链,从而定位到问题代码。假如经过分析后发现内存中的对象都是“必须存活”的对象,这时候就要思考下项目中是否把“-Xms跟-Xmx”设置得太小了(当然这里也不是随意调大,需要结合机器的物理内存情况),再者需要留意代码中是否有一些长生命周期的对象,从代码中优化内存消耗。
2、方法区溢出
在jvm的方法区中,它主要存放了类的信息,常量,静态变量等。在jdk8以前是通过“-XX:PermSize,-XX:MaxPermSize”来调整这个区域的值,但是从8开始呢,永久代的概念被MetaSpace(元空间)代替了,对应的参数也变成了“-XX:MetaspaceSize,-XX:MaxMetaspaceSize”。在这个例子中使用CGLib来动态生成一些类,方便我们实验操作。
/**
* VM Args: -XX:MetaspaceSize=5m -XX:MaxMetaspaceSize=5m
* @author wangzenghuang
*/
public class MethodAreaOOMDemo {
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[] objects, MethodProxy methodProxy) throws Throwable {
return methodProxy.invokeSuper(obj,objects);
}
});
enhancer.create();
}
}
static class OOMObject{}
}
运行结果
Exception in thread "main" java.lang.OutOfMemoryError: Metaspace
简单解决方法
这个问题的话,一般来说根据情况调整方法区的大小就行了,网上也有人说可以去掉MetaSpace的的大小限制,但是不建议这么干,毕竟不可控的事情我们要少点干,很容易给自己埋雷。
3.栈溢出
对于我们来说,还有一个熟悉的错误,那就是“StackOverflowError”,它是由线程请求的栈深度超过了jvm允许的最大范围而产生的。“-Xss”参数可以设置栈容量。
/**
* VM Args: -Xss128k
* @author wangzenghuang
*/
public class StackOFDemo {
private static int stackLength = 1; public void stackLeak(){
stackLength++;
stackLeak();
} public static void main(String[] args) {
StackOFDemo stackOFDemo = new StackOFDemo();
try {
stackOFDemo.stackLeak();
}catch (Throwable e){
System.out.println("length : "+ stackLength);
throw e;
}
}
}
运行结果
length : 983
Exception in thread "main" java.lang.StackOverflowError
at StackOFDemo.stackLeak(StackOFDemo.java:10)
at StackOFDemo.stackLeak(StackOFDemo.java:10)
...
简单解决思路
一般来说此类问题多出现在存在递归的地方,要从代码里重新审视递归未结束的原因,若递归的方法没问题可以根据实际情况调整“-Xss”参数的大小。还有一些代码的循坏依赖也会造成此类情况,
4.直接内存溢出
本机直接内存默认与“-Xmx”设定的值一样大,可以通过“-XX:MaxDirectMemorySize”修改。
/**
* VM Args: -Xmx20m -XX:MaxDirectMemorySize=10
* @author wangzenghuang
*/
public class DirectMemoryOOMDemo {
private static final int _1MB = 1024 * 1024; public static void main(String[] args) throws IllegalAccessException {
Field field = Unsafe.class.getDeclaredFields()[0];
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null);
while (true){
unsafe.allocateMemory(_1MB);
}
}
}
运行结果
呃,一运行这段代码idea直接闪退了,查阅其他资料可以得知当DirectMemory导致内存溢出时,Heap Dump文件是很小的,如果程序中有使用NIO的情况可以检查一下。
总结
这里所展示的代码只是可以触发jvm的各种错误,但是并不代表这是唯一的触发错误的方方式,假如我们的代码比较复杂,有时候遇到类似错误的时候还是需要耐心分析。
该文章首发于微信公众号《深夜里的程序猿》,转载请注明出处,侵权必究。
论JVM爆炸的几种姿势及自救方法的更多相关文章
- 论JVM爆炸的几种姿势及自救方法,你不得不知!
前言 如今不管是在面试还是在我们的工作中,OOM总是不断的出现在我们的视野中,所以我们有必要去了解一下导致OOM的原因以及一些基本的调整方法,大家可以通过下面的事例来了解一下什么样的代码会导致OOM, ...
- 【bzoj3224】Tyvj 1728 普通平衡树 01Trie姿势+平衡树的四种姿势 :splay,旋转Treap,非旋转Treap,替罪羊树
直接上代码 正所谓 人傻自带大常数 平衡树的几种姿势: AVL Red&Black_Tree 码量爆炸,不常用:SBT 出于各种原因,不常用. 常用: Treap 旋转 基于旋转操作和随机数 ...
- 快速了解IOC的几种姿势
一.首先我们了解IOC如何注入的几种姿势 构造函数注入(Constructor Injection) Ioc容器会智能的选择和调用合适的构造函数以创建依赖的对象.如果被选择的构造函数具有相应的参数,I ...
- 两个文件去重的N种姿势
最近利用shell帮公司优化挖掘关键词的流程,用shell替代了多个环节的操作,极大提高了工作效率. shell在文本处理上确有极大优势,比如多文本合并.去重等,但是最近遇到了一个难搞的问题,即两个大 ...
- 又拍云张聪:OpenResty 动态流控的几种姿势
2019 年 1 月 12 日,由又拍云.OpenResty 中国社区主办的 OpenResty × Open Talk 全国巡回沙龙·深圳站圆满结束,又拍云首席架构师张聪在活动上做了< Ope ...
- 补习系列(7)-springboot 实现拦截的五种姿势
目录 简介 姿势一.使用 Filter 接口 1. 注册 FilterRegistrationBean 2. @WebFilter 注解 姿势二.HanlderInterceptor 姿势三.@Exc ...
- python打开文件的N种姿势
# python打开文件的N种姿势 print('[1]使用open()函数+简单for循环') f1 = open('python.txt') for line in f1: print(line. ...
- [转]地图投影的N种姿势
此处直接给出原文链接: 1.地图投影的N种姿势 2.GIS理论(墨卡托投影.地理坐标系.地面分辨率.地图比例尺.Bing Maps Tile System)
- SpringBoot系列教程web篇Servlet 注册的四种姿势
原文: 191122-SpringBoot系列教程web篇Servlet 注册的四种姿势 前面介绍了 java web 三要素中 filter 的使用指南与常见的易错事项,接下来我们来看一下 Serv ...
随机推荐
- 再次实践 MySQL chart - 每天5分钟玩转 Docker 容器技术(166)
学习了 chart 结构和模板的知识后,现在重新实践一次 MySQL chart,相信会有更多收获. chart 安装前的准备 作为准备工作,安装之前需要先清楚 chart 的使用方法.这些信息通常记 ...
- ArcCore重构-Platform_Types.h实现辨析
AUTOSAR定义了一系列PlatformTypes,如uint8/uint16/uint32等等基本类型. It contains all platform dependent types and ...
- margin-right没有效果的问题
margin-right其实有效果的,只是在默认即标准流的情况的下显示不出来效果.如果脱离标准流呢?想到这个,就立马在css文件中加了一个:float:right;然后在测试的时候就能看到margin ...
- 团队项目第二阶段个人进展——Day9
一.昨天工作总结 冲刺第九天,完成图片的优化,与队友一起讨论如何合并并优化 二.遇到的问题 无 三.今日工作规划 合并后优化
- 使用EHCache需要注意的几个问题(转)
最近做一个小项目,需要对一批数据进行缓存,且要求持久化到磁盘.使用ehcache非常简单和直观,一般来说只需要配置ehcache.xml文件,接着直接使用@Cacheable, @Cacheput, ...
- 并发库应用之十三 & 并发集合类的应用
传统集合实现同步的问题 举了一个例子:Map集合线程不同步导致的问题. 解决办法:使用同步的Map集合 使用集合工具类中的方法将不同步的集合转为同步的Collections.synchronizedM ...
- SSM-MyBatis-03:Mybatis中简单的整合日志
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥-------------简单的整合日志,首先提供俩种方式,log4j和logback简单的说一下logback,他由log4j的原作者编 ...
- linux实时文件事件监听--inotify
一.inotify简介 inotify是Linux内核2.6.13 (June 18, 2005)版本新增的一个子系统(API),它提供了一种监控文件系统(基于inode的)事件的机制,可以监控文件系 ...
- Get,Post请求方式经典详解
本文转自:http://blog.csdn.net/findsafety/article/details/47129021 前几天工作中,所有表单我都采用post方法,头儿说那样不好,大型网站上一般都 ...
- 修改WordPress后台默认登陆地址提高网站安全性
作者:荒原之梦 原文链接:http://zhaokaifeng.com/?p=536 安装完WordPress后,默认的登陆地址就是: http://XXX.XXX/wordpress/wp-admi ...