工作中最常见的6种OOM问题
前言
最近我写的几篇线上问题相关的文章:《糟糕,CPU100%了》《如何防止被恶意刷接口》《我调用第三方接口遇到的13大坑》发表之后,在全网广受好评。
今天接着线上问题这个话题,跟大家一起聊聊线上服务出现OOM问题的6种场景,希望对你会有所帮助。
1 堆内存OOM
堆内存OOM是最常见的OOM了。
出现堆内存OOM问题的异常信息如下:
java.lang.OutOfMemoryError: Java heap space
此OOM是由于JVM中heap的最大值,已经不能满足需求了。
举个例子:
public class HeapOOMTest {
public static void main(String[] args) {
List<HeapOOMTest> list = Lists.newArrayList();
while (true) {
list.add(new HeapOOMTest());
}
}
}
这里创建了一个list集合,在一个死循环中不停往里面添加对象。
执行结果:
出现了java.lang.OutOfMemoryError: Java heap space的堆内存溢出。
很多时候,excel一次导出大量的数据,获取在程序中一次性查询的数据太多,都可能会出现这种OOM问题。
我们在日常工作中一定要避免这种情况。
2 栈内存OOM
有时候,我们的业务系统创建了太多的线程,可能会导致栈内存OOM。
出现堆内存OOM问题的异常信息如下:
java.lang.OutOfMemoryError: unable to create new native thread
给大家举个例子:
public class StackOOMTest {
public static void main(String[] args) {
while (true) {
new Thread().start();
}
}
}
使用一个死循环不停创建线程,导致系统产生了大量的线程。
执行结果:
如果实际工作中,出现这个问题,一般是由于创建的线程太多,或者设置的单个线程占用内存空间太大导致的。
建议在日常工作中,多用线程池,少自己创建线程,防止出现这个OOM。
3 栈内存溢出
我们在业务代码中可能会经常写一些递归
调用,如果递归的深度超过了JVM允许的最大深度,可能会出现栈内存溢出问题。
出现栈内存溢出问题的异常信息如下:
java.lang.StackOverflowError
例如:
public class StackFlowTest {
public static void main(String[] args) {
doSamething();
}
private static void doSamething() {
doSamething();
}
}
执行结果:
出现了java.lang.StackOverflowError栈溢出的错误。
我们在写递归代码时,一定要考虑递归深度。即使是使用parentId一层层往上找的逻辑,也最好加一个参数控制递归深度。防止因为数据问题导致无限递归的情况,比如:id和parentId的值相等。
4 直接内存OOM
直接内存
不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。
它来源于NIO
,通过存在堆中的DirectByteBuffer
操作Native内存,是属于堆外内存
,可以直接向系统申请的内存空间。
出现直接内存OOM问题时异常信息如下:
java.lang.OutOfMemoryError: Direct buffer memory
例如下面这样的:
public class DirectOOMTest {
private static final int BUFFER = 1024 * 1024 * 20;
public static void main(String[] args) {
ArrayList<ByteBuffer> list = new ArrayList<>();
int count = 0;
try {
while (true) {
// 使用直接内存
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);
list.add(byteBuffer);
count++;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} finally {
System.out.println(count);
}
}
}
执行结果:
会看到报出来java.lang.OutOfMemoryError: Direct buffer memory直接内存空间不足的异常。
5 GC OOM
GC OOM
是由于JVM在GC时,对象过多,导致内存溢出,建议调整GC的策略。
出现GC OOM问题时异常信息如下:
java.lang.OutOfMemoryError: GC overhead limit exceeded
为了方便测试,我先将idea中的最大和最小堆大小都设置成10M:
-Xmx10m -Xms10m
例如下面这个例子:
public class GCOverheadOOM {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < Integer.MAX_VALUE; i++) {
executor.execute(() -> {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
}
});
}
}
}
执行结果:
出现这个问题是由于JVM在GC的时候,对象太多,就会报这个错误。
我们需要改变GC的策略。
在老代80%时就是开始GC,并且将-XX:SurvivorRatio(-XX:SurvivorRatio=8)和-XX:NewRatio(-XX:NewRatio=4)设置的更合理。
最近就业形式比较困难,为了感谢各位小伙伴对苏三一直以来的支持,我特地创建了一些工作内推群, 看看能不能帮助到大家。
你可以在群里发布招聘信息,也可以内推工作,也可以在群里投递简历找工作,也可以在群里交流面试或者工作的话题。
进群方式
添加苏三的私人微信:su_san_java,备注:博客园+所在城市,即可加入。
6 元空间OOM
JDK8
之后使用Metaspace
来代替永久代
,Metaspace是方法区在HotSpot
中的实现。
Metaspace不在虚拟机内存中,而是使用本地内存也就是在JDK8中的ClassMetadata
,被存储在叫做Metaspace的native memory。
出现元空间OOM问题时异常信息如下:
java.lang.OutOfMemoryError: Metaspace
为了方便测试,我修改一下idea中的JVM参数,增加下面的配置:
-XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m
指定了元空间和最大元空间都是10M。
接下来,看看下面这个例子:
public class MetaspaceOOMTest {
static class OOM {
}
public static void main(String[] args) {
int i = 0;
try {
while (true) {
i++;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOM.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
return methodProxy.invokeSuper(o, args);
}
});
enhancer.create();
}
} catch (Throwable e) {
e.printStackTrace();
}
}
}
执行结果:
程序最后会报java.lang.OutOfMemoryError: Metaspace的元空间OOM。
这个问题一般是由于加载到内存中的类太多,或者类的体积太大导致的。
好了,今天的内容先分享到这里,下一篇文章重点给大家讲讲,如何用工具定位OOM问题,敬请期待。
最后说一句(求关注,别白嫖我)
如果这篇文章对您有所帮助,或者有所启发的话,帮忙扫描下发二维码关注一下,您的支持是我坚持写作最大的动力。
求一键三连:点赞、转发、在看。
关注公众号:【苏三说技术】,在公众号中回复:面试、代码神器、开发手册、时间管理有超赞的粉丝福利,另外回复:加群,可以跟很多BAT大厂的前辈交流和学习。
工作中最常见的6种OOM问题的更多相关文章
- 数据科学中的常见的6种概率分布(Python实现)
作者:Pier Paolo Ippolito@南安普敦大学 编译:机器学习算法与Python实战(微信公众号:tjxj666) 原文:https://towardsdatascience.com/pr ...
- 十七、Java中数组常见的几种排序方法!
转载自:https://www.cnblogs.com/bekeyuan123/p/6891875.html 数组的定义: // 3种定义方式 int[] arr = new int[5]; int[ ...
- 汇编中PTR常见的几种用法
汇编中PTR的用法确实是令人比较头疼的,我特意搜集了一些PTR的应用实例,可以从例子中揣摩出规律: 1.MOV WORD PTR [DI],OFFSET BUF1 2.SUB BYTE ...
- java中最常见的几种运行时异常,你get了吗?
NullPointerException (空指针异常) ClassCastException (类型强制转换异常) NumberFormatException (数字格式异常) NegativeAr ...
- KETTLE4个工作中有用的复杂实例--1、数据定时自动(自动抽取)同步作业
今天呕心沥血花了8个小时给大家带来kettle工作中最常见的四种复杂实例,90%的项目用到这4种实例都可以解决. 4种实例种还有2种通用kettle工具,使用这两种通用工具实例,可以直接修改相应的配置 ...
- css布局 - 工作中常见的两栏布局案例及分析
突然想到要整理这么一篇平时工作中相当常见但是我们又很忽视的布局的多种处理方法.临时就在我经常浏览的网站上抓的相对应的截图.(以后看到其他类型的我再补充) 既然截了图,咱们就直接看人家使用的布局方式,毕 ...
- [工作中的设计模式]享元模式模式FlyWeight
一.模式解析 Flyweight在拳击比赛中指最轻量级,即“蝇量级”或“雨量级”,这里选择使用“享元模式”的意译,是因为这样更能反映模式的用意.享元模式是对象的结构模式.享元模式以共享的方式高效地支持 ...
- 简洁优雅的Python教你如何在工作中“偷懒”
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: A字头 PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...
- 教你如何在工作中“偷懒”,python优雅的帮你解决
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取htt ...
- 工作中常见的五种技术leader
力不从心型 在工作中有种技术leader,总认为自己是最好的.在方案设计的时候,自己有一种方案,下属有一种方案.leader非要别人听他的.如果两种方案没有优劣之分,比较建议的做法是让真正实施的人按照 ...
随机推荐
- 《ASP.NET Core 与 RESTful API 开发实战》-- (第8章)-- 读书笔记(下)
第 8 章 认证和安全 8.3 HTTPS HTTP 协议能够在客户端和服务器之间传递信息,特点是以明文的方式发送内容,并不提供任何方式的数据加密 为了解决 HTTP 协议这一缺陷,需要使用另一种协议 ...
- 吉特日化MES & WMS 与周边系统集成架构
作者:情缘 出处:http://www.cnblogs.com/qingyuan/ 关于作者:从事仓库,生产软件方面的开发,在项目管理以及企业经营方面寻求发展之路 版权声明:本文版权归作者和博客园 ...
- JOISC 2019 记录
Day1 T1 Examination 三维数点板子题,直接 cdq分治+树状数组,时间复杂度 \(O(n\log^2n)\). Day1 T2 Meetings 对于一个大小为 \(n\) 的树,我 ...
- JS leetcode 买卖股票的最佳时机 题解分析,我离职了。
壹 ❀ 引 昨天下班后,还是找经理提出了辞职,没有犹豫的裸辞,今天与人事的对话不小心被后台的同事听到,一下在公司传开了,下午我与同事们多人对线,被他们的消息轰炸....没错,我真的要走了. 因为什么原 ...
- NC200179 Colorful Tree
题目链接 题目 题目描述 A tree structure with some colors associated with its vertices and a sequence of comman ...
- Java 递归的方式将list集合的某一字段拼接单个String
场景介绍 要将list 集合中的某一个字段合并成一个字符串,并且要用符号 "|" 分割开每个拼接后的字段. 一个例子胜于一切的文字表达,拼接后的结果如下 str1|str2|str ...
- java 注解结合 spring aop 实现日志traceId唯一标识
MDC 的必要性 日志框架 日志框架成熟的也比较多: slf4j log4j logback log4j2 我们没有必要重复造轮子,一般是建议和 slf4j 进行整合,便于后期替换为其他框架. 日志的 ...
- Laravel入坑指南(6)——Redis缓存
写在前面: Redis是常用nosql服务之一,在Redis官网上最新的稳定版本是6.0.6.这里不讨论Redis服务如何编译,如何使用.在Redis官网有很健全的文档. 这里要讨论的是无论在cent ...
- 微信小程序获取本日、本周、本月、本年时间段
原文链接 https://cslaoxu.vip/110.html 说明 最近需要用到统计不同时间段内的记录数,所以找了一下现成的工具类.下面就演示一下如何引用到实际项目中. 详细用法请参考:http ...
- Vue+SpringBoot+ElementUI实战学生管理系统-6.院系管理模块
1.章节介绍 前一篇介绍了用户管理模块,这一篇编写院系管理模块,需要的朋友可以拿去自己定制.:) 2.获取源码 源码是捐赠方式获取,详细请QQ联系我 :)! 3.实现效果 院系列表 修改院系 4.模块 ...