我需要找出我真正接近OutOfMemoryError
的时间,以便我可以将结果刷新到文件并调用runtime.gc();
。我的代码是这样的:
Runtime runtime = Runtime.getRuntime();
...
if ((1.0 * runtime.totalMemory() / runtime.maxMemory()) > 0.9) {
... flush results to file ...
runtime.gc();
}
有更好的方法吗?有人可以帮我一把吗?
我明白我正在以这种方式玩火,所以我推断出一种更加坚实而简单的方法来确定我什么时候吃饱了。我目前正在使用Jena模型,所以我做了一个简单的检查:如果模型有超过550k的语句,那么我刷新所以我没有冒任何风险。
答案 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上,您可能正在运行大量内存。在这种情况下,这种方法几乎肯定会遇到很多困难。