Exception in thread “pool-5-thread-4“ java.lang.OutOfMemoryError: Java heap space

本文讨论了在执行算法性能测试时遇到的JavaheapspaceOutOfMemoryError,介绍了JVM内存结构,重点讲解了如何通过调整JVM启动参数(如-Xms和-Xmx)以及使用工具(如jinfo、jmap等)来解决内存溢出问题,同时提到了Java版本检查和使用jstack进行线程分析的重要性。
摘要由CSDN通过智能技术生成

1、错误

执行算法性能测试时,出现Exception in thread "pool-5-thread-4" java.lang.OutOfMemoryError: Java heap space

2、分析

java.lang.OutOfMemoryError: Java heap space

在JVM中内存一共有3种:Heap(堆内存),Non-Heap(非堆内存) [3]和Native(本地内存)。 

上面这个是Heap(堆内存)OutOfMemoryError。堆内存是运行时分配所有类实例和数组的一块内存区域。

网上资料参考:

Java.lang.OutOfMemoryError: Java heap space
原因:Heap内存溢出,意味着Young和Old generation的内存不够。
解决:解决方案有两种,一是优化应用,找到消耗大量内存的地方,然后优化代码或者算法。这种方式比较推荐,但是难度比较大,尤其是在产品环境中出现这种问题,开发人员不能很好的重现问题。第二种方案是提升Java heap size,这种方式虽然感觉有点治标不治本,但是可行性非常高,操作简单。

 “JVM 堆空间溢出(java.lang.OutOfMemoryError: Java heap space)”错误是JVM 堆空间不足,此时只需要调整-Xms 和-Xmx 这两个参数即可。

堆内存溢出时,首先判断当前最大内存是多少(参数:-Xmx 或 -XX:MaxHeapSize=),可以通过命令 jinfo -flag MaxHeapSize 查看运行中的JVM的配置,如果该值已经较大则应通过 mat 之类的工具查找问题,或 jmap -histo查找哪个或哪些类占用了比较多的内存。参数-verbose:gc(-XX:+PrintGC) -XX:+PrintGCDetails可以打印GC相关的一些数据。如果问题比较难排查也可以通过参数-XX:+HeapDumpOnOutOfMemoryError在OOM之前Dump内存数据再进行分析。此问题也可以通过histodiff打印多次内存histogram之前的差值,有助于查看哪些类过多被实例化,如果过多被实例化的类被定位到后可以通过btrace再跟踪。
下面代码可再现该异常:
List<String> list = new ArrayList<String>();
while(true) list.add(new String("Consume more memory!"));

2.2、查看Java版本

[root@localhost ]# java -version
java version "1.8.0_221"
Java(TM) SE Runtime Environment (build 1.8.0_221-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode)

3、这次的解决办法:

3.1、解决办法

从两个方面入手来解决:一是排查程序是否有BUG导致内存泄漏;二是调整JVM启动参数增大内存。

因为使用的数据大小是100M,所以我这里需要执行该算法时,用的是调整JVM启动参数增大内存

执行时加上:java -Xms20480m -Xmx20480m  就可以了。

 

3.2、-Xms和-Xmx参数说明

尽量把这两个参数的值设置称一样的,因为在运行中弹性扩容或减少容量都会带来性能损耗。

-Xms与Xmx分别是设置jvm的堆内存的初始大小和量大大小。

-Xmx2048m:等价于-xx:MaxHeapSize,设置JVM的最大堆内存为2028M。

-Xms512m:等价于-xx:InitialHeapSize,设置JVM初始堆内存为512M。

适当的调整JVM的内存大小,可以充分利用服务器资源,让程序跑得更快。

4、其他信息

4.1、查看java进程得方式

1、通过ps -ef|grep java 命令来查看
2、通过jps命令来查看所有java进程
13424 是java进程ID
17632是jps本身得进程ID

4.2、jps -l查询完整的包名

[root@localhost 1772455281197334529]# jps -l
9437 sdkPerfTest-1.0.8_2.3.8.9_algorithm20240326.jar
23356 sun.tools.jps.Jps

4.3、 jinfo -flags pid: 查看曾经赋过值的参数值

jinfo(Configuration Info for Java) 查看虚拟机配置参数信思,也可用于调整虚拟机的配置参数。

$jinfo -flags 9437

[root@localhost sdkPerTest]# jinfo -flags 9437
Attaching to process ID 10006, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.221-b11
Non-default VM flags: -XX:CICompilerCount=12 -XX:InitialHeapSize=1054867456 -XX:MaxHeapSize=16861102080 -XX:MaxNewSize=5620367360 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=351272960 -XX:OldSize=703594496 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC 
Command line:  -Djava.ext.dirs=/opt/casb/lib/:/home/jdk/jre/lib/ext:/home/jdk/lib/ext

4.4、jinfo -flag <具体参数> pid: 查看具体参数的值

[root@localhost sdkPerTest]# jinfo -flag MaxHeapSize  9437
-XX:MaxHeapSize=16861102080

参考:jvm 性能调优工具之 jinfo命令详解-CSDN博客

参考:JVM知识梳理之四_JVM运维与调试工具 - 知乎 (zhihu.com)

4.5、jinfo -sysprops pid :查看该进程的全部配置信息

4.6、top看资源利用率

#13424是进程ID

top |grep 9437

4.7、jstat命令查看GC

jstat是用于监视JVM各种运行时的状态信息的命令行工具,包括类加载、内存、垃圾收集、即时编译等运行时数据。

$jstat -gc 2187487 500 10

# 使用jstat查看目标进程2187487 的垃圾收集状况,每500ms查看一次,共查看 10 次
# 如果不加后面两个参数,则表示只查看一次
# -gc 表示查看的是垃圾收集状况

上述-gc表示查看垃圾收集状况,其中各列的含义如下(内存空间单位:KB,时间单位:秒):

  • S0C :幸存者0区容量
  • S1C :幸存者1区容量
  • S0U :幸存者0区已使用大小
  • S1U :幸存者1区已使用大小
  • EC :eden区容量
  • EU :eden区已使用大小
  • OC :老年代容量
  • OU :老年代已使用大小
  • MC :元数据空间容量
  • MU :元数据空间已使用大小
  • CCSC :压缩类空间容量
  • CCSU :压缩类空间已使用大小
  • YGC :年轻代GC次数
  • YGCT :年轻代GC耗时合计
  • FGC :整堆GC次数
  • FGCT :整堆GC耗时合计
  • GCT :所有GC耗时合计

其中,CCS是压缩类空间,用于对象指针与类指针压缩,属于MetaSpace元数据空间的一部分,通过-XX:+UseCompressedClassPointers-XX:+UseCompressedOops开启,默认开启。

-gc是参数选项,可以替换为以下其他选项:

4.8、jstack pid查看线程信息

jstack用于生成虚拟机当前时刻的线程快照。生成线程快照主要是为了定位长时间停顿的线程,比如线程间死锁、死循环、请求外部资源超时等等。通过jstack可以查看到各个线程的调用堆栈信息,就可以知道线程目前运行在哪一句代码,在做什么事情或者等待什么资源。

$jstack 2205220

备注:

学习JDK自带的那些工具比如jpsjinfojstatjstack等。

参考:JVM知识梳理之四_JVM运维与调试工具 - 知乎 (zhihu.com)

参考:java heap space 解决方法_Java中的OutOfMemoryError的各种情况及解决和JVM内存结构

  • 17
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宁宁可可

您的鼓励是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值