如何解决OutOfMemoryError

简介: 如果没遇到过OME错误,都不好意思说自己是做Java开发的。JVM最近更新文章的速度很慢,懒,另外我对时间的分配不太擅长,事情一旦多起来,就很容易焦头烂额,效率也变低,看起来一天忙忙碌碌,最后发现处理的事情并不多。

如果没遇到过OME错误,都不好意思说自己是做Java开发的。

img_9f963c967c918620a60b9cee9c2689f3.png
JVM

最近更新文章的速度很慢,懒,另外我对时间的分配不太擅长,事情一旦多起来,就很容易焦头烂额,效率也变低,看起来一天忙忙碌碌,最后发现处理的事情并不多。但是在不多的事情中,每天其实在程序开发上都会遇到一些值得分享的事情,如果一直没有动笔记录,很多事情都慢慢的忘记了。所以不管怎么忙,我想还是把工作中遇到技术上的问题,拿出来分享给大家,帮大家少踩坑。也是自己工作的一次记录。

OME的发生

OutOfMemoryError异常可以说是一个比较棘手的问题,Java中所有的对象都存储在堆中,通常如果JVM无法再分配新的内存,内存耗尽,垃圾回收无法及时回收内存,就会抛出OutOfMemoryError。

我这次遇到的OME错误如图:


img_cd7336cbc97384b8ec00dc414237b40e.png
image.png

报错误的原因是因为: 执行垃圾收集的时间比例太大, 有效的运算量太小. 默认情况下, 如果GC花费的时间超过 98%, 并且GC回收的内存少于 2%, JVM就会抛出这个错误。

解决方案

都是自己写的程序,报这个错误,自己心里能没有点数吗,我里面写了一个大对象,实例化之后会不断的加载网络数据到内存中,并且我没有销毁这个对象,继续使用这个对象,同时设置了线程一直让此对象进行等待。

然后我修改大对象在使用之后指向null。压力就没这么大了。

JVM内存区域

可能对JVM了解的不够清晰,下面再整理下JVM的一些常用知识点。

JVM的自动内存管理可以归结为两个问题:

  • 给对象分配内存
  • 回收分配的内存

经常变动堆内存区域为:新生代(Eden),存活区(Survivor),老年代(Old)
Perm Gen:为持久带,主要存放Java类的类信息,与垃圾收集要收集的Java对象关系
不大。
Code Cache:主要存放代码缓存,它主要用于存放JIT所编译的代码,JIT编译器是在程序运行期间,将Java字节码编译成平台相关的二进制代码。正因为此编译行为发生在程序运行期间,所以该编译器被称为Just-In-Time编译器。JIT主要编译的是热点代码。


img_4a7e689984fbf8ff7ce55b31144d4d6c.png
内存区域图

关键点:

  • 大多数情况下,对象在新生代Eden区中分配,Eden区域不够的时候,虚拟机发动一次Minor GC,对象在发生Minor GC后仍能存活,那么对象将被移动到Suvivor空间中,每经过一次Minor GC,对象的年龄增加1岁,增加到一定的年龄(默认15岁),就会晋升到老年代Old Gen。
  • 大对象是指需要连续内存空间的Java对象,典型的大对象是那种很长的字符串及数组。大对象对内存分配来说就是一个坏消息。 像爬虫爬取的整个页面,分配成字符串就是占用内存很多的字符串。
  • 在发生MinorGC之前,虚拟机会先检查老年代的最大可用连续空间十分大于新生代的所有对象空间,如果成了,那么Minor GC就是安全的。如果不是,那么检查HandlePromotionFailure是否允许担保失败,如果允许,那么检查老年代的最大可用空间是否大于之前晋升到老年代对象的平均大小,如果大于那么也尝试进行一次Minor GC。 如果小于,或者HandlePromotionFailure设置为不允许冒险,那么改成进行一次Minor GC。

两张Jconsole的JVM图:

img_d268d409212110d5afab3f1313f0e7f3.png
image.png
img_635800a8a1ec7aaba25ffd50007e0c2b.png
image.png

常见的JVM设置参数

可以在命令行直接查看可以设置的参数:


img_900f949b655dbb15ef2a970c7c8dc5ab.png
java

img_2370fc2ba7eee56d16c2e2bcceca6638.png
java -X

img_d47ffa7bf66c8a1b30606870a4c050a0.png
java -XX:+PrintFlagsFinal

-XX:NewRatio:年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)
-XX:SurvivorRatio:Eden区与Survivor区的大小比值
-XX:+DisableExplicitGC 关闭System.gc()
-XX:MaxTenuringThread 对象在Suvivor区域中的年龄到达多少进入Old Gen
-XX:PretenureSizeThreshold 另大于这个设置值的对象直接在老年代分配,避免Eden区和Suvivor区域之间大量的内存分配

这篇文章里面也列举了不少参数:
https://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html

最后

不断的进步。希望能帮助到大家。

目录
相关文章
|
2月前
|
存储 Java
什么情况下会产生StackOverflowError(栈溢出)和OutOfMemoryError(堆溢出)怎么排查
什么情况下会产生StackOverflowError(栈溢出)和OutOfMemoryError(堆溢出)怎么排查
|
4月前
|
缓存 架构师 算法
Java内存溢出如何解决,Java oom排查方法,解决办法
在Java开发过程中,有效的内存管理是保证应用程序稳定性和性能的关键。不正确的内存使用可能导致内存泄露甚至是致命的OutOfMemoryError(OOM)。
|
4月前
|
缓存 架构师 算法
Java内存溢出如何解决,Java oom排查方法,10个定位解决办法
在Java开发过程中,有效的内存管理是保证应用程序稳定性和性能的关键。不正确的内存使用可能导致内存泄露甚至是致命的OutOfMemoryError(OOM)。
|
8月前
|
存储 Java 应用服务中间件
JVM各种情况内存溢出分析
JVM各种情况内存溢出分析
191 0
|
10月前
|
SQL 存储 Java
【问题处理】—— 一次内存溢出(OutOfMemoryError)实战排查
【问题处理】—— 一次内存溢出(OutOfMemoryError)实战排查
188 0
|
12月前
|
IDE Java 开发工具
JVM-03内存区域与内存溢出异常(下)【OutOfMemoryError案例】
JVM-03内存区域与内存溢出异常(下)【OutOfMemoryError案例】
81 0
|
存储 算法 Java
JVM04-JVM中内存溢出(包括内存泄露)以及其处理方法
上一篇我们介绍了JVM03–JVM垃圾收集机制的一些基本概念,这一篇介绍一下JVM中各种内存溢出(包括内存泄露)及其处理方法。 本文会按照JVM中内存划分来介绍各种内存溢出的例子。
182 0
JVM04-JVM中内存溢出(包括内存泄露)以及其处理方法
|
存储 Java 数据库连接
JVM之常见内存溢出(OutOfMemoryError)异常 ✨ 每日积累
JVM之常见内存溢出(OutOfMemoryError)异常 ✨ 每日积累
JVM之常见内存溢出(OutOfMemoryError)异常 ✨ 每日积累
|
Java fastjson 数据库
线上环境内存溢出-OutofMemoryError
公司线上环境,出现内存溢出异常,发生时,cpu占用360%。系统可用内存不足。
232 1
线上环境内存溢出-OutofMemoryError