Java VM突然没有明显的原因退出

Jor*_*orn 2 java jvm

我有一个问题,我的Java程序突然退出,没有任何异常抛出或程序正常完成.

我正在编写一个程序来解决Project Euler的第14个问题.这就是我得到的:

private static final int INITIAL_CACHE_SIZE = 30000;
private static Map<Long, Integer> cache = new HashMap<Long, Integer>(INITIAL_CACHE_SIZE);

public void main(String... args) {
    long number = 0;
    int maxSize = 0;

    for (long i = 1; i <= TARGET; i++) {
        int size = size(i);
        if (size > maxSize) {
            maxSize = size;
            number = i;
        }
    }
}
private static int size(long i) {
    if (i == 1L) {
        return 1;
    }
    final int size = size(process(i)) + 1;
    return size;
}

private static long process(long n) {
    return n % 2 == 0 ? n/2 : 3*n + 1;
}
Run Code Online (Sandbox Code Playgroud)

运行正常,使用目标1 000 000时,在大约5秒内正确完成.

我想通过添加缓存来优化,所以我将size方法更改为:

private static int size(long i) {
    if (i == 1L) {
        return 1;
    }
    if (cache.containsKey(i)) {
        return cache.get(i);
    }
    final int size = size(process(i)) + 1;
    cache.put(i, size);
    return size;
}
Run Code Online (Sandbox Code Playgroud)

现在,当我运行它时,它只是在我到达555144时停止(进程退出).每次都是相同的数字.没有异常,错误,Java VM崩溃或抛出任何东西.

更改缓存大小似乎也没有任何影响,因此缓存引入如何导致此错误?

如果我强制执行缓存大小不仅仅是初始,而是像这样永久:

    if (i < CACHE_SIZE) {
        cache.put(i, size);
    }
Run Code Online (Sandbox Code Playgroud)

错误不再发生.编辑:当我将缓存大小设置为2M时,错误会再次开始显示.

任何人都可以复制这个,甚至可以提供一个关于它为什么会发生的建议吗?

Jos*_*non 8

这只是一个没有打印的OutOfMemoryError.如果我设置了较高的堆大小,程序运行正常,否则它会以未记录的OutOfMemoryError退出(尽管在调试器中很容易看到).

您可以通过传递此JVM arg并重新运行程序来验证这一点并获得堆转储(以及发生OutOfMemoryError的打印输出):

-XX:+ HeapDumpOnOutOfMemoryError

有了它,它将打印出这样的效果:

java.lang.OutOfMemoryError:Java堆空间

堆转储到java_pid4192.hprof ... 创建堆转储文件[在4964秒中91901809字节]

比如使用-Xmx200m来增加堆大小,你就不会有问题 - 至少对于TARGET = 1000000.