鉴于此代码,我们加载大量数据,将其写入文件,然后运行exe ..
void myMethod() {
Map stuff = createMap(); //Consumes 250 MB memory
File file = createFileInput(stuff); //Create input for exe
runExectuable(file); //Run Windows exe
}
在运行exe之前释放stuff
消耗的内存的最佳方法是什么?我们不再需要在内存中,因为我们已将数据转储到文件以输入到exe ...
是在stuff = null
之前设置runExecutable(file)
的最佳方法吗?
答案 0 :(得分:4)
可能最好的答案是:什么也不做。
Java编译器非常聪明。它可以告诉stuff
之后不再需要createFileInput(stuff)
并重写代码以确保它是GCable。如果您想100%确定,可以将其设置为null,但编译器可能已经为您完成了此操作。并将其设置为null并不能保证它将是GC。
首先尝试进行一些分析,我想你会发现内存已经被释放了。天真地检查你的代码以找到你认为存在内存问题的地方很少会有很好的结果。获取一些数据。
编辑:请注意,编译器可以是javac
或JIT编译器。两者都非常清楚这样的事情并进行各种你无法想象的优化。底线:编写干净的代码,然后对其进行分析并从那里进行优化。
EDIT2:对于那些对JVM使用内存的技巧感兴趣的人,我想推荐这个博客(它很好地解释了这个特殊问题):http://jeremymanson.blogspot.com/2010/02/garbage-collection-softreferences.html
答案 1 :(得分:1)
如果您对@noah建议的内容(什么都不做)感到不舒服,或者代码是在没有JIT或常见运行时优化的环境中运行的,那么将一个更清晰的替代方法设置为null并调用System .gc()将分解你的代码。
void myMethod() {
File file = prepareFile(); //Prepare file for window exe
runExectuable(file); //Run Windows exe
}
private File prepareFile() {
Map stuff = createMap(); //Consumes 250 MB memory
return createFileInput(stuff); //Create input for exe
}
这是一个更清晰的代码,一旦它超出范围,就可以让东西符合收集资格。显式设置为null并调用gc()只是黑客攻击。
答案 2 :(得分:0)
可替换地:
runExecutable(createFileInput(createMap()));
请注意,createFileInput
方法不会保留对Map
实例的引用!
答案 3 :(得分:0)
将地图对象设置为null是个好主意。在将map设置为null之后,您甚至可以尝试显式地执行System.gc()。
但请记住,垃圾收集器只能按照自己的计划工作,并且做其中任何一个都不能保证垃圾收集器会在那时运行它 但是如果你的Map设置为null,你就不会在正常情况下得到OutOfMemory,因为在最坏的情况下,当jvm达到最大堆大小时,它肯定会运行垃圾收集,因此内存将被释放。
答案 4 :(得分:0)
void myMethod() {
runExectuable(createFile()); //Run Windows exe
}
File createFile() {
Map stuff = createMap(); //Consumes 250 MB memory
return createFileInput(stuff); //Create input for exe
}
答案 5 :(得分:0)
由于Map的东西是在方法内部声明的,所以一旦方法退出就应该有资格进行垃圾收集。
答案 6 :(得分:0)
@jpalecek你认为System.gc()在内存运行不足时会如何完成jvm调用的任何其他垃圾收集?自动垃圾收集就是这个意思。
答案 7 :(得分:0)
我首先想到的不是改变引用范围或强制垃圾收集,但可以减少内存需求吗?
是否可以重构功能以允许在写入文件时生成 stuff ?例如,你可以将createMap和creatFile减少到计算地图部分的东西
while (mapFiller.hasMore()) {
Map map = mapFiller.getNextPartialMap();
mapWriter.writePartialMap(map);
}
内存减少将是我的第一种方法,因为即使你让JVM回收内存,这并不意味着它必然会将它释放回操作系统。
另见: JVM sending back memory to OS和Java VM - does the freed memory return to the OS?
答案 8 :(得分:-2)
将stuff
设置为null
肯定是必要的,但如果不强制进行垃圾回收,那就不够了。我想runExecutable
函数会在执行完成之前等待,所以我会在另一个线程中运行System.gc()
,以便在等待时发生垃圾收集。