java file 到 byte[]_小白java系列-OOM问题排查实例

452ce332839fda3ec15be1fd0b0c94a6.png

通常jvm程序消失,或者内存占用过大

1.java程序占用内存过大,被操作系统杀掉

2.java程序出现OOM

出现OOM首先要拿到HeapDump日志信息

有以下方法:

  • java运行中添加-XX:HeapDumpOnOutMemoryError参数
  • jmap -dump:live,live,format=b,file="路径" pid
    (pid可以通过jps获取) 可以获取正在运行堆栈信息,但jmap都在线上运行会影响线上线程,所以可在测试环境下进行重现方式
  • 使用阿里的 arthas https://arthas.aliyun.com/doc/quick-start.html
    使用步骤:
curl -O https://arthas.aliyun.com/arthas-boot.jar
#显示全部进程 选择需要观察的序号
java -jar arthas-boot.jar
#选了序号后 等待片刻进入目标进程
#dump到指定文件
heapdump /tmp/dump.hprof
#只dump live对象
heapdump --live /tmp/dump.hprof
#介绍几个其他常用的指令
dashboard #展示当前进程的信息
thread id #打印线程ID的栈信息
thread -b #可以查看方便查看死锁
jad *.class #可以获取class的反编译代码相关信息,如下。

[arthas@961]$ jad TestOutMemory
ClassLoader: 
+-sun.misc.Launcher$AppClassLoader@73d16e93
 +-sun.misc.Launcher$ExtClassLoader@a2c976a 
 
Location:                   
/mnt/prepare/java/ 
/*
 * Decompiled with CFR.
 */
import java.util.HashMap;
​
public class TestOutMemory {
 public static void main(String[] arrstring) throws InterruptedException {
 HashMap<Integer, byte[]> hashMap = new HashMap<Integer, byte[]>();
 for (int i = 1000; i > 0; --i) {
 Thread.sleep(1000L);
 hashMap.put(i, new byte[0x100000]);
        }
    }
}
​
Affect(row-cnt:1) cost in 86 ms.
​

那么这个除了反编译还有什么作用,可以进行热修改。见这篇文章

HiroLin:小白java系列-使用阿里arthas进行线上热更新​zhuanlan.zhihu.com
dc9a40e34c9b210652aee9aba42018b0.png

对日志进行分析

有如下工具:

  • jvisualvm
  • EAT (Eclipse Memory Analyzer Tool) 可单独下载http://www.eclipse.org/mat/downloads.php
  • jprofiler(收费)

重现OOM定位

代码:

package com.hiro.learn.outMemory;
​
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
​
/**
 * Project: learn
 *
 * @author : hirolin
 * @date : 2020/10/8 17:39
 */
public class TestOutMemory {
​
    public static void main(String[] args) throws InterruptedException {
        Map temp = new HashMap();
        for (int i = 1000; i > 0; i--) {
            Thread.sleep(500);
            System.out.println(i);
            temp.put(i, new byte[1024 * 1024]);//生产1M的占用
        }
    }
}

那么如果指定当前堆大小, -Xmx10M -Xms10M -XX:+HeapDumpOnOutOfMemoryError

堆得最大最小大小最好设置一样,避免堆内存分配或大或小抖动,当然根据实际场景合理设置

那么在循环10次左右就会oom,且无法回收。控制台输出如下:

1000
999
998
997
996
995
994
993
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid23784.hprof ...
Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceHeap dump file created [8867828 bytes in 0.050 secs]

可以看到内存溢出溢出:堆满了,泄露:内存中存在一直不会被回收的区域

使用idea设置headdump文件,文件生成后在工程当前目前下。

  • 此时使用jvisualvm打开java_pid23784.hprof文件。

可以看到byte占用最高。

98608acb774cce026189e1c72f5e5e01.png
  • EMT更为详细信息

f97b9d9d1bd59e122a39298c2fa072d5.png

通常我主要看这两个tap。histogram和leak suspects

可以看到占用最大内存对象引用情况,方便定位到源头。

bde7cac8384efccb9530e578eb9c57ff.png

第二个是推测可能出现问题的地方:

c4f1fa383e61fcf80b64efcadbcad646.png

可以看到上述已经描述了有一个本地变量一直占用了内存,对应代码中的byte处问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值