在回答了关于如何用Java强制释放对象的问题(这个人正在清除一个1.5GB的HashMap)后System.gc(),我被告知System.gc()手动调用是不好的做法,但这些评论并不完全令人信服.此外,似乎没有人敢投票,也没有人回答我的回答.
我被告知这是不好的做法,但后来我也被告知垃圾收集器运行不再系统地停止世界,并且它也可以有效地被JVM用作提示,所以我有点像茫然
我知道JVM在需要回收内存时通常比你知道的要好.我也明白,担心几千字节的数据是愚蠢的.我也明白,甚至数兆字节的数据也不是几年前的数据.但仍然,1.5千兆字节?而且你知道内存中有1.5 GB的数据; 它不像是在黑暗中拍摄.是System.gc()系统性的坏,还是有一点它变得好吗?
所以问题实际上是双重的:
System.gc()?它是否仅仅是某些实现中JVM的提示,还是一个完整的收集周期?真的有垃圾收集器实现可以在不停止世界的情况下完成工作吗?请详细说明人们在评论中对我的回答所做的各种断言.System.gc(),或者有时候可以接受?如果是这样,那些时候是什么时候?我们有一个长期存在的服务器进程,很快就需要大量的RAM.我们看到,一旦JVM从操作系统获得内存,它就永远不会将其返回给操作系统.我们如何要求JVM将堆内存返回给操作系统?
通常,这些问题的接受答案是使用
-XX:MaxHeapFreeRatio和-XX:MinHeapFreeRatio.(参见例如
1,2,3,4).但是我们像这样运行java:
java -Xmx4G -XX:MaxHeapFreeRatio=50 -XX:MinHeapFreeRatio=30 MemoryUsage
Run Code Online (Sandbox Code Playgroud)
仍然在VisualVM中看到这个:
显然,JVM并不尊重,-XX:MaxHeapFreeRatio=50因为heapFreeRatio非常接近100%而且远不及50%.无需点击"执行GC"即可将内存返回给操作系统.
MemoryUsage.java:
import java.util.ArrayList;
import java.util.List;
public class MemoryUsage {
public static void main(String[] args) throws InterruptedException {
System.out.println("Sleeping before allocating memory");
Thread.sleep(10*1000);
System.out.println("Allocating/growing memory");
List<Long> list = new ArrayList<>();
// Experimentally determined factor. This gives approximately 1750 MB
// memory in our installation.
long realGrowN = 166608000; //
for (int i = 0 ; i < realGrowN …Run Code Online (Sandbox Code Playgroud)