Java heap 内存溢出(java.lang.OutOfMemoryError: Java heap space)

产生原因:

  • 代码中使用大对象:Java8的JVM会将大对象直接分配到Old Generation中,Old Generation的数据只会在FULL GC的时候被回收;Full GC执行机制(暂不清楚);未执行Full GC的情况下,如果再次创建大对象,那么大对象还会导致JVM去申请新的Old Generation空间;但Old Generation不会无限增大(应该有上限吧:个人经历:32G Ubuntu系统,未指定任何JVM参数,Eden、From、To各1G左右大小,Old Generation 5G大小);当大对象和大对象的垃圾数据(没有被回收的实际不用的大对象)总量超过上限的时候就会引发heap内存溢出

现象:

使用Parallel GC 看到的现象

  • 环境:Ubuntu 16.04.3;jdk1.8.0_65;默认的虚拟机(从jmap结果看使用的GC机制是Parallel GC)
  • 现象
    查看现象的命令:jmap -heap 进程pid
root@xxxxx:~# jmap -heap 10134
Attaching to process ID 10134, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.65-b01

using thread-local object allocation.
Parallel GC with 13 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 8434745344 (8044.0MB)
   NewSize                  = 176160768 (168.0MB)
   MaxNewSize               = 2811232256 (2681.0MB)
   OldSize                  = 352321536 (336.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 937426944 (894.0MB)
   used     = 378428264 (360.8973159790039MB)
   free     = 558998680 (533.1026840209961MB)
   40.36882729071632% used
From Space:
   capacity = 936902656 (893.5MB)
   used     = 37279688 (35.55268096923828MB)
   free     = 899622968 (857.9473190307617MB)
   3.9790353630932604% used
To Space:
   capacity = 936902656 (893.5MB)
   used     = 0 (0.0MB)
   free     = 936902656 (893.5MB)
   0.0% used
PS Old Generation
   capacity = 5623513088 (5363.0MB)
   used     = 4640311792 (4425.346176147461MB)
   free     = 983201296 (937.6538238525391MB)
   82.51624419443336% used

这个现象可以已经执行过某些GC了,不是报错当时的jmap信息

使用Concurrent Mark-Sweep GC 看到的现象

待补充

解决办法

  • 修改逻辑将使用大对象的处理逻辑修改成不使用大对象的逻辑(个人感觉根治的办法)
  • 临时处理办法,增加heap的大小;因为电脑的内存实际有32G且仅使用一个服务;所以使用-Xmx16G增加了heap的大小
  • 执行完代码逻辑后执行Full GC(如何执行暂未尝试,待更新)
  • 尝试使用其他GC机制(Concurrent Mark-Sweep GC)
    开启方式 -XX:+UseConcMarkSweepGC

相关内容

如何手动执行Full GC
使用命令:jcmd 进程pid GC.run

  • 执行前现象:
root@xxxxx:~# jmap -heap 12090
Attaching to process ID 12090, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.65-b01

using thread-local object allocation.
Parallel GC with 13 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 8434745344 (8044.0MB)
   NewSize                  = 176160768 (168.0MB)
   MaxNewSize               = 2811232256 (2681.0MB)
   OldSize                  = 352321536 (336.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 2552758272 (2434.5MB)
   used     = 1785468960 (1702.7558898925781MB)
   free     = 767289312 (731.7441101074219MB)
   69.94273525950209% used
From Space:
   capacity = 132120576 (126.0MB)
   used     = 36294088 (34.61273956298828MB)
   free     = 95826488 (91.38726043701172MB)
   27.470428224593874% used
To Space:
   capacity = 126353408 (120.5MB)
   used     = 0 (0.0MB)
   free     = 126353408 (120.5MB)
   0.0% used
PS Old Generation
   capacity = 1842872320 (1757.5MB)
   used     = 1086944064 (1036.5906372070312MB)
   free     = 755928256 (720.9093627929688MB)
   58.980975090016% used

38675 interned Strings occupying 4184088 bytes
  • 执行命令:
root@xxxxx:~# jcmd 12090 GC.run
12090:
Command executed successfully
  • 执行后现象:
root@xxxxx:~# jmap -heap 12090
Attaching to process ID 12090, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.65-b01

using thread-local object allocation.
Parallel GC with 13 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 8434745344 (8044.0MB)
   NewSize                  = 176160768 (168.0MB)
   MaxNewSize               = 2811232256 (2681.0MB)
   OldSize                  = 352321536 (336.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 2552758272 (2434.5MB)
   used     = 18458080 (17.602996826171875MB)
   free     = 2534300192 (2416.897003173828MB)
   0.7230641538784914% used
From Space:
   capacity = 126353408 (120.5MB)
   used     = 0 (0.0MB)
   free     = 126353408 (120.5MB)
   0.0% used
To Space:
   capacity = 120061952 (114.5MB)
   used     = 0 (0.0MB)
   free     = 120061952 (114.5MB)
   0.0% used
PS Old Generation
   capacity = 1842872320 (1757.5MB)
   used     = 37773024 (36.023162841796875MB)
   free     = 1805099296 (1721.4768371582031MB)
   2.0496820962615576% used

38275 interned Strings occupying 4151424 bytes.

执行Full GC之后可以明显看出各个区的占用变小

问题

下列问题如果有清楚的大牛请在留言处给与讲解先谢过了
Full GC执行机制
Heap有默认上限?还是每个space有默认上限?默认上限如何计算出来的?
参见Java Doc的Default Heap Size讲解部分
此处说明heap是有上限的,物理内存小于192MB的时候,默认上限是物理内存的一半,当物理内存>=1G的时候,heap的上限是物理内存的1/4

多大的对象会被认为是大对象?
如何计算一个对象的大小?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值