当我接近OutOfMemoryError时如何在java中确定?

时间:2014-03-04 11:25:04

标签: java runtime out-of-memory heap-size

我需要找出我真正接近OutOfMemoryError的时间,以便我可以将结果刷新到文件并调用runtime.gc();。我的代码是这样的:

Runtime runtime = Runtime.getRuntime();
...
if ((1.0 * runtime.totalMemory() / runtime.maxMemory()) > 0.9) {
... flush results to file ...
  runtime.gc();
}

有更好的方法吗?有人可以帮我一把吗?

修改

我明白我正在以这种方式玩火,所以我推断出一种更加坚实而简单的方法来确定我什么时候吃饱了。我目前正在使用Jena模型,所以我做了一个简单的检查:如果模型有超过550k的语句,那么我刷新所以我没有冒任何风险。

2 个答案:

答案 0 :(得分:3)

首先:如果您想确定自己是否接近OutOfMemoryError,那么您所要做的就是将当前内存与{{{}使用的最大内存进行比较1}},以及你已经做过的事情。

第二次:您希望将结果刷新到文件,我想知道为什么要在接近JVM的情况下执行此操作,您只需使用类似{{1}的内容它有一个缓冲区,所以如果缓冲区被填满,它将自动刷新结果。

第三次:不要明确调用OutOfMemoryError,这是一种不好的做法,而是优化FileWriter内存参数:

GC

另外

JVM

这些将加速GC。

-Xmx -> this param to set the max memory that the JVM can allocate -Xms -> the init memory that JVM will allocate on the start up -XX:MaxPermSize= -> this for the max Permanent Generation memory 启用-XX:MaxNewSize= -> this need to be 40% from your Xmx value -XX:NewSize= -> this need to be 40% from your Xmx value 旧空间。

答案 1 :(得分:1)

这似乎有效:

public class LowMemoryDetector {

    // Use a soft reference to some memory - will be held onto until GC is nearly out of memory.
    private final SoftReference<byte[]> buffer;
    // The queue that watches for the buffer to be discarded.
    private final ReferenceQueue<byte[]> queue = new ReferenceQueue<>();
    // Have we seen the low condition?
    private boolean seenLow = false;

    public LowMemoryDetector(int bufferSize) {
        // Make my buffer and add register the queue for it to be discarded to.
        buffer = new SoftReference(new byte[bufferSize], queue);
    }

    /**
     * Please be sure to create a new LMD after it returns true.
     * 
     * @return true if a memory low condition has been detected.
     */
    public boolean low () {
        // Preserve that fact that we've seen a low.
        seenLow |= queue.poll() != null;
        return seenLow;
    }
}

private static final int OneMeg = 0x100000;

public void test() {
    LowMemoryDetector lmd = new LowMemoryDetector(2*OneMeg);
    ArrayList<char[]> eatMemory = new ArrayList<>();
    int ate = 0;
    while ( !lmd.low() ) {
        eatMemory.add(new char[OneMeg]);
        ate += 1;
    }
    // Let it go.
    eatMemory = null;
    System.out.println("Ate "+ate);
}

打印

Ate 1070

对我来说。

使用大于您正在使用的最大分配单位的缓冲区大小。它需要足够大,以便在释放缓冲区时满足任何分配请求。

请记住,在64位JVM上,您可能正在运行大量内存。在这种情况下,这种方法几乎肯定会遇到很多困难。