什么,系统内存溢出了?记一次JVM调优实战

1 篇文章 0 订阅
0 篇文章 0 订阅

这里我们不讲JVM的内存划分,垃圾判定算法,垃圾回收算法,垃圾收集器等知识。主要讲的是实际调优的操作,对JVM调优感兴趣的可以看下去。至于垃圾回收算法,可以看看我这篇文章:

垃圾回收算法-微信搜:Lvshen的技术小屋

公司系统出现内存溢出的故障,下面是内存溢出排除过程,我采用伪代码模拟了生产环境。

public class MemoryLeakService {

    public List<User> distinct() throws InterruptedException {
        List<User> list = new ArrayList<>();
        CountDownLatch downLatch = new CountDownLatch(1);
        new Thread(() -> {
            try {
                for (int j = 0; j < 100; j++) {
                    for (int i = 0; i < 100000; i++) {
                        User user = new User(String.valueOf(i));

                        if (!list.contains(user)) {
                             list.add(user);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                downLatch.countDown();
            }
        }).start();
        downLatch.await();
        return list;
    }
    public static void main(String[] args) throws InterruptedException {
        System.out.println(Thread.currentThread());
        new Thread().start();
        new MemoryLeakService().distinct();
    }
}

这里主要是模拟一个缓存加载的过程,将用户数据加载进List集合中。为了体现效果,我们将堆内存调小,并将内存溢出的堆栈信息打印出来,具体指令如下:

-Xmx8m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/temp/20200824.hprof

当运行系统时,出现如下报错

我们发现Thread-1的堆空间内存溢出了,并且生成如下文件20200824.hprof

打开内存分析工具 Eclipse Memory Analyzer

加载20200824.hprof文件,找到有问题的堆栈信息

控制台打印显示Thread-1由内存溢出,我们进Thread-1看

点击箭头处按钮

选择线程明细

我们发现MemoryLeakService第24行代码有问题,看看第24行代码

是这个对象导致的。

仔细看代码,发现User对象存入了List集合中

if (!list.contains(user)) {
 list.add(user);
}

看看contains()源码

发现这里是比较的地址值,那!list.contains(user)永远为true。这里就相当于List存了个User

我们需要重写Userequals方法

@Override
public boolean equals(Object o) {
    if (this == o) {
     return true;
    }
    if (o == null || getClass() != o.getClass()) {
     return false;
    }
    User user = (User) o;
    return Objects.equals(id, user.id);
}

@Override
public int hashCode() {
 return Objects.hash(id, name, age);
}

再次运行,没有出现内存溢出了。

好了,上面就是一次简单的内存溢出查找的过程了,关于工具Eclipse Memory Analyzer的使用,自己可以去网上下载下来,练习使用下。说不定哪天你们的系统真的出现内存溢出,自己就有用武之地了。

往期推荐

扫码二维码,获取更多精彩。或微信搜Lvshen_9,可后台回复获取资料

1.回复"java" 获取java电子书;

2.回复"python"获取python电子书;

3.回复"算法"获取算法电子书;

4.回复"大数据"获取大数据电子书;

5.回复"spring"获取SpringBoot的学习视频。

6.回复"面试"获取一线大厂面试资料

7.回复"进阶之路"获取Java进阶之路的思维导图

8.回复"手册"获取阿里巴巴Java开发手册(嵩山终极版)

9.回复"总结"获取Java后端面试经验总结PDF版

10.回复"Redis"获取Redis命令手册,和Redis专项面试习题(PDF)


另:点击【我的福利】有更多惊喜哦。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值