作为一个没有感情的代码杀手,写代码的时候难免写出一个死循环啥的,或者动不动造成内存泄漏直到内存溢出,那也是难免并且情有可原的。但是我们不能只是做一个简单的代码复制工具人,我们写的bug,我们当然也要直到怎么去解决它咯。
好的,今天就来记录下,如果解决内存溢出的问题。
制造一起内存溢出事故
机智的我当然不可能故意拿着实际项目来弄一个内存溢出的事故咯,这样做了怕是见不到明天的太阳了。所以这里写一个例子,写个循环一直往map里面丢数据,直到溢出:
/**
* 内存泄露直到溢出
*/
public class DumpDemo {
private static final int _1MB = 1024 * 1024;
public static void main(String[] args) {
System.out.println("-------------mytime----------------");
Map<String,Object> m = new HashMap<>();
int i = 0;
do{
byte[] test = new byte[_1MB];
m.put(String.valueOf(i), test);
i++;
}while(i<100000);
}
}
内存溢出什么时候出现?
首先,内存溢出什么时候出现,我们当然不知道咯?所以要合理利用jvm的命令工具的嘛。jmap工具可以将堆栈的信息dump下hrop文件来。
jmap -dump:format=b,file=heap.hprof PID
但是这个是不方便的,这个需要我们主动去dump,并且还需要进程PID。
然后jvm还提供了一个可视化工具jvisualvm,这个工具可以直观的看到堆栈的信息。
可以看到使用的堆一直在升高,这个时候我们可以堆dump下来文件。
但是这个也是需要我们自动去做。在之前的文件有说过jvm有提供在jvm堆内存溢出时自动dump文件下来。启动的时候加上配置就行。
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heap.hprof
这里就dump出一个这样的hprof快照文件,可以用jvisualvm本身的系统去分析,我这里推荐MAT。通过MAT分析工具堆dump下来的文件进行分析,他能帮你找出问题在哪里。
它发现是Map的问题里,所以我们可以点进去看下具体信息
这可以看到我们没有释放的资源,还能看到具体问题是在哪段代码。
到此完美收工。