论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 ...
随机推荐
- Solr(三)向solr-5.5.4中添加数据
Solr添加数据 一 首先在创建好的CORE中添加自己需要的Field(可以理解为表的字段) 1 切换到配置Field的文件目录,编辑配置Field的文件 managed-schema cd /usr ...
- javase---string类介绍01
一.String类简介 java.lang.String类用于描述一个字符序列.String类是不可变对象的类.其对象一旦被创建,永远无法改变.但是对象的引用可以重新赋值.而且String类被fina ...
- mysql数据库死锁的产生原因及解决办法
这篇文章主要介绍了mysql数据库锁的产生原因及解决办法,需要的朋友可以参考下 数据库和操作系统一样,是一个多用户使用的共享资源.当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同 ...
- Proxy是在什么时候调用InvocationHandler的invoke方法的
最近看到spring的动态代理,扒到深处看到时 Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);看到这一句,顿时比较懵逼,还是 ...
- Maven install命令理解
每一个构建都需要唯一的坐标来标识位置,我们根据坐标位置就能够下载构建至本地仓库.那么如果我们是内部项目,自定义的构建并不公开至网络上,项目成员又想依赖他怎么办呢?想想maven找寻构建的步骤. 先找寻 ...
- redHat linux 修改防火墙设置简略版
1) 重启后生效 开启: chkconfig iptables on 关闭: chkconfig iptables off 2) 即时生效,重启后失效 开启: service iptables sta ...
- SqlSugar 盲点
1.读取数据库连接 private SqlSugarClient GetInstance() { string conmstring = System.Web.Configuration.WebCon ...
- 概率与统计推断第二讲homework
作业目的: 体会条件独立 1.现需要设计一个根据一个人是否是学生$S$(布尔变量)和其体重$W$(连续变量)判断该人的性别$G$(布尔变量).假设在给定$G$的情况下$S$和$W$独立,且假设概率分布 ...
- 【转】linux系统中如何进入退出vim编辑器,方法及区别
在linux家族中,vim编辑器是系统自带的文本编辑器,其功能强大自不必说了. 偶有小白,刚接触linux,要修改某个文本文件,不可能像WINDOWS那样操作,更有甚者,进入VI编辑器后,无法退出以致 ...
- 下载恒星源码使用vs2015运行配置
需要安装PostgreSQL 配置安装路径下的include 项目 右键→属性 在启动项目项目中配置 右键→属性→展开连接器→输入