idea内存溢出解决_各种OOM代码样例及解决方法

针对目前大家对OOM的类型不太熟悉,那么来总结一下各种OOM出现的情况以及解决方法。把各种OOM的情况列出来,然后逐一进行代码编写复现和提供解决方法。

1. 堆溢出-java.lang.OutOfMemoryError: Java heap space。

2. 栈溢出-java.lang.OutOfMemorryError。

3. 栈溢出-java.lang.StackOverFlowError。

4. 元信息溢出-java.lang.OutOfMemoryError: Metaspace。

5. 直接内存溢出-java.lang.OutOfMemoryError: Direct buffer memory。

6. GC超限-java.lang.OutOfMemoryError: GC overhead limit exceeded。

0x01: 堆溢出异常,相信大家很常见。即堆内对象不能进行回收了,堆内存持续增大,这样达到了堆内存的最大值,数据满了,所以就出来了。我们直接放溢出的代码样例。需要设置好idea的VM Options: -Xmx100m,这样设置为最大堆内存,这样运行起来就很快就出来错误了。

package oom;import java.util.ArrayList;import java.util.List;import java.util.concurrent.TimeUnit;public class HeapOOM {    static class OOMObject {    }    public static void main(String[] args) throws InterruptedException {        List list = new ArrayList<>();        while(true) {//            TimeUnit.MILLISECONDS.sleep(1);            list.add(new OOMObject());        }    }}

运行的异常如下,代码直接就出来我们看到的异常了。

/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java -Xmx100mException 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 oom.HeapOOM.main(HeapOOM.java:21)Process finished with exit code 1

细心的小伙伴可以发现代码中设置了一个休眠,目的是看一下堆内存的结构和数据图。将休眠代码打开,然后打开JDK自带的jconsole命令,连接上之后看一下概览图,通过下图发现堆内存持续不断的增长。

f055c8fe2140ca97082ba27f3bf78462.png

打开内存界面,看一下内存,然后点一下GC按钮,这个时候会有一些类进行回收,但是还是会继续增长,看一下下面的图。

a26d4d70626b1b4833e323e400b6347a.png
1dc7a29e2870a1558ff77b1bc0768e2a.png

点开信息标签看一下。经过几次GC回收之后,类的数据量还是变化不大,说明没有进行回收。

711aaa162e3db205fbd001c5176a8fbb.png

以上这种情况的解决方法就是找到问题点,分析哪个地方是否存储了大量类没有被回收的情况,通过JMAP命令将线上的堆内存导出来后进行分析。

0x02: 看一下栈溢出的情况,下面的代码就是无限的创建线程,直到没法再创建线程。

package oom;import java.util.concurrent.TimeUnit;/** * @Date 2020-07-18 */public class StackOOM {    public static void infiniteRun() {        while(true) {            Thread thread = new Thread(() -> {                while (true) {                    try {                        TimeUnit.HOURS.sleep(1);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            });            thread.start();        }    }    public static void main(String[] args) {        infiniteRun();    }}

抛出来的异常如下,如果真的需要创建线程,我们需要调整帧栈的大小-Xss512k,默认帧栈大小为1M,如果设置小了,可以创建更多线程。

/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java -Xss512k Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread    at java.lang.Thread.start0(Native Method)    at java.lang.Thread.start(Thread.java:717)    at oom.StackOOM.infiniteRun(StackOOM.java:24)    at oom.StackOOM.main(StackOOM.java:29)Process finished with exit code 130 (interrupted by signal 2: SIGINT)

以上这种情况是帧栈不够用了,如果出现了这种情况,需要了解什么地方创建了很多线程,线上程序需要用jstack命令,将当前线程的状态导出来放到文件里边,然后将文件上传到fastthread.io网站上进行分析。

0x03:看一下栈溢出的另一种情况,这就是栈的StackOverFlow的情况。下面就是一个死循环递归调用。

package oom;/** * @Date 2020-07-18 */public class StackOFE {    public static void stackOverFlowErrorMethod() {        stackOverFlowErrorMethod();    }    public static void main(String[] args) {        stackOverFlowErrorMethod();    }}

运行之后出现的错误如下,程序每次递归的时候,程序会把数据结果压入栈,包括里边的指针等,这个时候就需要帧栈大一些才能承受住更多的递归调用。通过-Xss进行设置,上边的例子需要设置小一些,以分配更多的帧栈,这次是一个帧栈需要记录程序数据,所以需要更大的值。

/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java -Xss2mException in thread "main" java.lang.StackOverflowError    at oom.StackOFE.stackOverFlowErrorMethod(StackOFE.java:10)    at oom.StackOFE.stackOverFlowErrorMethod(StackOFE.java:10)    at oom.StackOFE.stackOverFlowErrorMethod(StackOFE.java:10)    at oom.StackOFE.stackOverFlowErrorMethod(StackOFE.java:10)    at oom.StackOFE.stackOverFlowErrorMethod(StackOFE.java:10)    at oom.StackOFE.stackOverFlowErrorMethod(StackOFE.java:10)

遇到上面的情况下,那么就需要通过jstack将线程数据导到文件进行分析。找到递归的点,如果程序就是需要递归的次数的话,那么这个时候就需要增大帧栈的大小以适应程序。

0x04: 元数据区域溢出,元数据区域也成为方法区,存储着类的相关信息,常量池,方法描述符,字段描述符,运行时产生大量的类就会造成这个区域的溢出。我们运行的时候指定一下元数据区域的大小,设置到idea的VM options里边:-XX:MetaspaceSize=10M -XX:MaxMetaspaceSize=30M。

package oom;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/** * @Date 2020-07-18 */public class MetaspaceOOM {    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();        }    }}

运行的结果如下,元数据信息溢出了。这种情况产生的原因有:通过CBLIG大量生成类,导致Meta信息满了;JDK7的时候使用String.intern()不当,会产生大量常量数据;加载大量的jsp以及动态生成jsp文件。需要调整元数据空间的大小,如果调大了之后还出现了这种异常,我们需要分析哪里出现的溢出并fix掉。

/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java -XX:MetaspaceSizeException in thread "main" java.lang.OutOfMemoryError: Metaspace    at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:345)    at net.sf.cglib.proxy.Enhancer.generate(Enhancer.java:492)    at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:114)    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291)    at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:480)    at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:305)    at oom.MetaspaceOOM.main(MetaspaceOOM.java:28)Process finished with exit code 1

0x05: 直接内存溢出,除了使用堆内存外,还可能用直接内存,即堆外内存。NIO为了提高性能,避免在Java Heap和native Heap中切换,所以使用直接内存,默认情况下,直接内存的大小和对内存大小一致。堆外内存不受JVM的限制,但是受制于机器整体内存的大小限制。如下代码设置堆最大内存为128m,直接内存为100m,然后我们每次分配1M放到list里边。  

-Xmx128m -XX:MaxDirectMemorySize=100Mpackage oom;import java.nio.ByteBuffer;import java.util.ArrayList;import java.util.List;/** * @Date 2020-07-18 */public class DirectBufferOOM {    public static void main(String[] args) {        final int _1M = 1024 * 1024 * 1;        List buffers = new ArrayList<>();        int count = 1;        while (true) {            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(_1M);            buffers.add(byteBuffer);            System.out.println(count++);        }    }}

这个时候,当输出100次的时候,下次再分配的时候会报OOM-Direct buffer memory。

/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java -Xmx128m Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory    at java.nio.Bits.reserveMemory(Bits.java:694)    at java.nio.DirectByteBuffer.(DirectByteBuffer.java:123)    at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)    at oom.DirectBufferOOM.main(DirectBufferOOM.java:18)Process finished with exit code 1

这种情况是我们使用直接内存造成溢出,这个时候我们需要检查一下程序里边是否使用的NIO及NIO,比如Netty,里边的直接内存的配置。

0x06: JDK1.6之后新增了一个错误类型,如果堆内存太小的时候会报这个错误。如果98%的GC的时候回收不到2%的时候会报这个错误,也就是最小最大内存出现了问题的时候会报这个错误。如果代码配置了最小最大堆内存都为10m。

-Xmx10m -Xms10mpackage oom;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * @Date 2020-07-18 */public class GCOverheadOOM {    public static void main(String[] args) {        ExecutorService executor = Executors.newFixedThreadPool(5);        for (int i = 0; i  {                try {                    Thread.sleep(10000);                } catch (InterruptedException e) {                    //do nothing                }            });        }    }}

这个创建了一个线程池,如果线程池执行的时候如果核心线程处理不过来的时候会把数据放到LinkedBlockingQueue里边,也就是堆内存当中。这个时候我们需要检查-Xms -Xmx最小最大堆配置是否合理。再一个dump出现当前内存来分析一下是否使用了大量的循环或使用大量内存代码。

以上就是经常遇到的情况,需要针对出现的不同情况进行分析和处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/533105.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

win7安装硬盘后无法启动计算机,硬盘装Win7系统电脑后开机提示DISK BOOT FAILURE怎么办【图文】...

很多人都喜欢安装win7系统&#xff0c;而硬盘安装系统的方式也是深受用户们的喜欢&#xff0c;但是最近有用户反映说硬盘安装win7系统之后&#xff0c;在重启计算机的时候屏幕提示DISK BOOT FAILURE,INSERT SYSTEM DISK AND PRESS ENTER&#xff0c;导致无法正常进入系统&#…

导入数据中文乱码_基于Navicat和Kettle的数据迁移完全解读(多图)

需求描述对于数据分析人员来说&#xff0c;工作的基础是数据&#xff0c;没有数据分析就无从谈起&#xff0c;即巧妇难为无米之炊。#数据库# #数据迁移# #Oracle# 然而&#xff0c;数据分析往往在实验环境或者准生产环境中开展&#xff0c;而数据分布在生产环境&#xff0c;因此…

怎样能确保计算机安全,如何确保电脑安全

如何确保电脑安全电脑安全问题层出不穷&#xff0c;如何确保电脑安全呢?下面是小编分享的一些方法&#xff0c;一起来看一下吧。一、关闭默认共享大部分的电脑系统在默认的情况下都是自动开启网络共享设置的&#xff0c;Win7系统也不例外&#xff0c;该功能主要是为了用户能够…

点云平面提取_基于LiDAR点云数据滤波方法

基于LiDAR点云数据滤波方法机载激光雷达所获取的数据被称为“点云(points cloud)”它在三维空间中呈现出随机分布的形状。在点云中&#xff0c;有些点属于真实的地形表面的点&#xff0c;有些点属于人工建筑物塔、输电线、桥等或自然植被如树、灌木、草、其他植物。激光雷达数据…

全国计算机一级书红色封面,年度最强的网红录取通知书,竟然附赠了一张黑胶唱片...

这两天世超被一张来自中国科学院大学的录取通知书给刷屏了&#xff0c;这份录取通知书里还附赠了一张黑胶光盘。光盘上刻录了一份国科大为新生准备的特别的礼物 —— 一段来自宇宙深处的声音。它们是由国科大师生通过 500 米口径球面射电望远镜( FAST )捕获的 15 颗脉冲星信号&…

动态新增表字段_制作动态的数据透视表(一):定义名称法创建数据透视表

——施瓦辛格&#xff1a;没有跌倒过的人不会成功。我们的日常工作中&#xff0c;会经常遇到一种情况&#xff1a;创建好数据透视表后&#xff0c;有其他被遗漏的数据内容需要重新插入到数据源后&#xff0c;有其他被遗漏的数据内容需要重新插入到数据源中&#xff1b;或者是需…

计算机公式or,【转载】 odds、OR和RR的计算公式和实际意义

1. OddsOdds 的意思为机率、可能性&#xff0c;是指某事件发生的可能性(概率)与不发生的可能性(概率)之比。假如某药物有疗效的比例为p1&#xff0c;则无效的比为1-p1&#xff0c;则odds的计算公式为&#xff1a;对于如下表所示的四格表&#xff0c;患病组的中暴露的概率(以实测…

系统相机裁剪比例_拍照时图片比例怎么选?比构图还要提前一步的摄影攻略要做好...

谈到摄影第一步&#xff0c;很多人都在说构图&#xff0c;但是比构图还要提前一步的&#xff0c;是选择合适的拍摄比例。在拍照时&#xff0c;始终是把要拍的东西装进设备的取景器里面&#xff0c;所以取景器的比例是16:9&#xff0c;还是4:3或者其他&#xff0c;就直接影响了我…

源码安装mysql_CentOS 7中源码安装MySQL 5.7.16 (亲测成功)

最近在CentOS 7中源码安装MySQL 5.7.16&#xff0c;发现MySQL5.7.6以后的安装方式真的与以前版本的MySQL安装方式大大的不同呀。不自己安装一把&#xff0c;下面这篇文章是通过自己的安装过程总结的一篇安装教程&#xff0c;有需要的朋友们可以参考借鉴&#xff0c;下面来一起看…

css动画定义,CSS3中Animation动画的定义和调用

现在经常会看到一些门户网站的专题使用到CSS3的动画&#xff0c;咋也不能落伍&#xff0c;在此这梳理下动画知识吧&#xff0c;便于后面用到。接下来介绍下Animation动画的定义和调用&#xff0c;在介绍Animation之前需要了解下Keyframes&#xff0c;英文意思就是关键帧&#x…

mysql5.7+proxy_mysql 5.7+mysql-proxy 0.8.5 读写分离

主从环境&#xff1a;mysql操做系统&#xff1a;CentOS6.5_x64linux主服务器Master&#xff1a;192.168.0.103sql从服务器Slave&#xff1a;192.168.0.105后端调度服务器MySQL-Proxy&#xff1a;192.168.0.104服务器1、mysql主从复制tcp2、mysql-proxy实现读写分离测试一、安装…

mysql 账户管理_Mysql账户管理原理与实现方法详解

本文实例讲述了Mysql账户管理原理与实现方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;账户管理在生产环境下操作数据库时&#xff0c;绝对不可以使用root账户连接&#xff0c;而是创建特定的账户&#xff0c;授予这个账户特定的操作权限&#xff0c;然后连接进行…

navicat for mysql 用户_Navicat for MySQL 怎么/怎么添加管理用户?Navicat for MySQL 添加管理用户教程_37游游网...

【37游游攻略】为了保证数据库的安全&#xff0c;对操作用户分级授权是非常有必要的&#xff0c;Navicat for MySQL 给我们提供了一个非常强悍又非常便捷的用户管理系统。点击位于连接右侧的用户命令&#xff0c;随之弹出管理用户的界面&#xff0c;Navicat for MySQL 系统默认…

js如何上传大文件到服务器,js将文件上传到远程服务器

js将文件上传到远程服务器 内容精选换一换将文件上传至Windows云服务器一般会采用MSTSC远程桌面连接的方式。本节为您介绍本地Windows计算机通过远程桌面连接&#xff0c;上传文件至Windows云服务器的操作方法。Windows云服务器可以访问公网。在本地Windows计算机上&#xff0c…

增强服务器安全性能,加强Linux服务器安全的20项建议

很多人都说 Linux 在默认配置下很安全&#xff0c;我在一定程度上同意这个说法(很值得商榷的话题)。不过 Linux 内置的安全模型和工具做得确实很到位&#xff0c;用户只需进行简单的调整和自定义就可以加强 Linux 服务器安全。与恶意用户做斗争对于所有 Linux 系统管理员来说都…

阴阳师师徒系统不同服务器,阴阳师体服师徒系统未收录改为随机SSR

昨天下午&#xff0c;受到很多争议的体服“师徒系统”更新啦&#xff01;新版的“师徒系统”修改了徒弟的条件&#xff0c;总的来说能剔除压级大佬&#xff0c;并且之前奖励未收录SSR降低为随机SSR式神&#xff0c;难怪很多阴阳师都说&#xff1a;“大快人心&#xff01;”的确…

Mysql union联合查询_Mysql联合查询union和union all的使用介绍

一、UNION和UNION ALL的作用和语法UNION 用于合并两个或多个 SELECT 语句的结果集&#xff0c;并消去表中任何重复行。UNION 内部的 SELECT 语句必须拥有相同数量的列&#xff0c;列也必须拥有相似的数据类型。同时&#xff0c;每条 SELECT 语句中的列的顺序必须相同.SQL UNION…

ios 查看同文件名_实战恢复cisco 2950交换机的IOS

本来想用两台思科交换机做实验的&#xff0c;可是通过console口进入其中一台交换机后却发现这个台交换机的IOS文件丢失了。本来正常进入交换机后应该是首先进入到用户模式的&#xff0c;而且提示符应该是“>”&#xff0c;而现在提示符却成了“&#xff1a;”&#xff0c;如…

repositoryitemlookupedit根据每行的id绑定数据_一种根据数据库自增ID生成唯一ID的解决方案...

在我们的开发过程中&#xff0c;经常会遇到ID生成的问题&#xff0c;那么这里就介绍一种解决方案&#xff0c;注意这里只适合混淆ID规则&#xff0c;也就是说生成的ID没有任何规则&#xff0c;不适用于订单ID。一般有序自增主键的ID&#xff0c;极易被爬虫抓取数据&#xff0c;…

bootstracp实现树形列表_Java实现一致性哈希算法,并搭建环境测试其负载均衡特性...

实现负载均衡是后端领域一个重要的话题&#xff0c;一致性哈希算法是实现服务器负载均衡的方法之一&#xff0c;你很可能已在一些远程服务框架中使用过它。下面我们尝试一下自己实现一致性哈希算法。一. 简述一致性哈希算法这里不详细介绍一致性哈希算法的起源了&#xff0c;网…