java层内存 oom,Java内存溢出OOM使用Mat分析

示例

package com.rumenz;

import java.util.ArrayList;

import java.util.List;

public class OutOfMemory {

public static void main(String[] args) {

List res=new ArrayList<>();

while (true){

res.add(new UserTest());

}

}

}

class UserTest{

}

VM 添加参数

-Xms20m -Xmx20m

输出:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

at com.rumenz.OutOfMemory.main(OutOfMemory.java:11)

解释:

通过VM参数控制JVM的堆内存大小只有20m,程序不停的创建对象,而对象又是在堆上分配内存,一直不停的向List中添加对象,没有垃圾回收,导致堆内存溢出(OutOfMemoryError).

Mat工具分析堆

2.VM参数加上: -XX:+HeapDumpOnOutOfMemoryError开启堆内存溢出导出堆内存到文件,默认在项目的根目录下.如果需要指定其它路径用-XX:HeapDumpPath=/tmp,会生成一个名字类似的java_pid28790.hprof文件.

3.使用Mat打开hprof文件

5b062f889b9b1506150ff137e98c0c3b.png

java.lang.Object[14053]含义: List本质上就是Object[]数组,14053就是里面存放的对象的个数.

Shallow Heap (浅层堆)表示:对象实际占用的堆大小(不包含其它引用对象的大小)

Retained Heap(保留堆)表示:对象实际占用+所包含引用对象的大小

Shallow Heap计算方法

在本次案例中:Shallow Heap占用112448字节,Retained Heap占用337296字节.

List res=new ArrayList<>(); res是局部变量,在栈上分配内存,res中存放的是UserTest实例对象的堆内存地址(引用),JDK1.8中打开指针压缩(-XX:+UseCompressedOops),在64位系统引用就占4个字节,未打开指针压缩64位系统中引用指针占用8个字节.

当前案例未打开指针压缩:

14053个引用地址占用内存大小: `14053*8=112424`,`Shallow Heap`占用`112448`字节,还有24字节明显就是res容器本身占用的内存大小.

数组浅堆占用内存计算:

16 bytes of overhead 对象的头

4 bytes length 存储容器长度

4 bytes padding 字节对其

16 bytes of overhead + 4 bytes length + 4 bytes padding = 24 bytes

Retained Heap计算方法

Retained Heap Size=Shallow Heap Size+引用对象实际大小

Shallow Heap 已经计算出来了 引用对象的实际大小:本案例中,由于UserTest是一个空的对象,所以每个UserTest实例对象就只占用16字节的对象头.总共有14053个实例对象,所以共占用14053*17=224848.

Retained Heap=112424+224848=337296和Mat分析的结果一致.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值