我有一个问题,我的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时,错误会再次开始显示.
任何人都可以复制这个,甚至可以提供一个关于它为什么会发生的建议吗?
这只是一个没有打印的OutOfMemoryError.如果我设置了较高的堆大小,程序运行正常,否则它会以未记录的OutOfMemoryError退出(尽管在调试器中很容易看到).
您可以通过传递此JVM arg并重新运行程序来验证这一点并获得堆转储(以及发生OutOfMemoryError的打印输出):
-XX:+ HeapDumpOnOutOfMemoryError
有了它,它将打印出这样的效果:
java.lang.OutOfMemoryError:Java堆空间
将
堆转储到java_pid4192.hprof ... 创建堆转储文件[在4964秒中91901809字节]
比如使用-Xmx200m来增加堆大小,你就不会有问题 - 至少对于TARGET = 1000000.
| 归档时间: |
|
| 查看次数: |
9185 次 |
| 最近记录: |