如何预测java.lang.OutOfMemory异常?

时间:2014-11-12 11:48:57

标签: java memory

是否可以通过编程方式进行?

这是我尝试过的:

import java.util.ArrayList;
import java.util.List;

public class TestMemory {

    public static void main(String[] args) {

        int kb = 1024;

        //Getting the runtime reference from system
        Runtime runtime = Runtime.getRuntime();

        //Print used memory
        System.out.println("Used Memory:" + (runtime.totalMemory() - runtime.freeMemory()) / kb);

        //Print free memory
        System.out.println("Free Memory:" + runtime.freeMemory() / kb);

        //Print total available memory
        System.out.println("Total Memory:" + runtime.totalMemory() / kb);

        //Print Maximum available memory
        System.out.println("Max Memory:" + runtime.maxMemory() / kb);

        List<String> list = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            for (int j = 0; j < 1000; j++) {
                list.add("abcdefghij" + i + j);
            }
            if (i % 1000 == 0) {
                try {
                    Thread.sleep(500);
                    System.out.println("Free Memory:" + runtime.freeMemory() / kb + " Kb");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}

和输出:

Used Memory:289
Free Memory:15582
Total Memory:15872
Max Memory:126720
Free Memory:15405 Kb
Free Memory:22820 Kb (long pause, longer than 500ms and then exception)
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOfRange(Arrays.java:2694)
    at java.lang.String.<init>(String.java:203)
    at java.lang.StringBuilder.toString(StringBuilder.java:405)
    at TestMemory.main(TestMemory.java:32)

对我来说并不是很重要。我希望崩溃前“可用内存”值减少。 如何写一个循环检查可用内存并通知我此异常之前的内存量?

3 个答案:

答案 0 :(得分:1)

我不认为这是尝试管理自己的程序以避免OutOfMemoryException的好方法。您必须在堆之前调整大小以满足您的内存需求。 无论如何,你的代码是正确的,但你需要在调用runtime.freeMemory()之前调用GC:System.gc()。

 if (i % 1000 == 0) {
            try {
                System.gc();
                Thread.sleep(500);
                System.out.println("Free Memory:" + runtime.freeMemory() / kb + " Kb");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

答案 1 :(得分:1)

我已将行if (i % 1000 == 0) {更改为if (i % 100 == 0) {

输出更改为:

Free Memory:73604 Kb
Free Memory:66637 Kb
Free Memory:54902 Kb
Free Memory:51044 Kb
Free Memory:44013 Kb
Free Memory:36982 Kb
Free Memory:27633 Kb
Free Memory:20661 Kb
Free Memory:13691 Kb
Free Memory:4352 Kb
Free Memory:54 Kb

该计划没有足够的时间来显示下降。

答案 2 :(得分:0)

我想说添加一个catch语句,当堆耗尽内存时会捕获它。您调用的方法返回系统中存在多少内存,而不是运行程序时为堆空间分配的内存。 JVM自己分配内存,而像C这样的语言需要调用malloc()来完成这项工作。