Gno*_*upi 6 java garbage-collection
出于内存优化的原因,我在分析期间启动自己的垃圾收集器,以检查在处理它们之后是否正确清理了对象.
但是,对垃圾收集器的调用是不够的,似乎无法保证清理它的内容.
有没有办法调用它,以确保它能够在分析条件下尽可能多地恢复(当然,这在生产中没有意义)?或者"多次调用"是"几乎可以肯定"的唯一方法?
或者我只是误解了垃圾收集器的一些事情?
一般来说,“完整的垃圾收集”是不明确的。GC 检测到无法访问的对象并回收它们。大多数 GC 实现都是在“循环”的基础上运行的,一旦运行了一个完整的循环,就可以定义“回收空间”的合理概念。因此,如果您可以运行一个完整的周期,并且该周期根本没有找到可回收的空间,并且应用程序处于“空闲”状态(例如不更新指针),那么您可以说您已经暂时达到了“完全收集”点。
因此,您可能想做类似的事情:
Runtime r = Runtime.getRuntime();
r.gc();
long f = r.freeMemory();
long m = r.maxMemory();
long t = r.totalMemory();
for (;;) {
r.gc();
long f2 = r.freeMemory();
long m2 = r.maxMemory();
long t2 = r.totalMemory();
if (f == f2 && m == m2 && t == t2)
break;
f = f2;
m = m2;
t = t2;
}
System.out.println("Full GC achieved.");
Run Code Online (Sandbox Code Playgroud)
该代码依赖于一些假设,其中最重要的是这Runtime.gc()不仅仅是一个“提示”,而且确实强制执行一些 GC 活动。Sun 的 JVM 可以使用“-XX:-DisableExplicitGC”标志启动,该标志转换Runtime.gc()为无操作,有效地防止上面的代码执行任何操作。
还有一些注意事项:
JVM 可能有一些后台连续活动,例如Timer线程。其中一些活动可能是“隐藏的”,即不是由应用程序开发人员编写的代码。另外,请考虑 AWT/Swing 事件调度程序线程。
GC 运行可能会通过可终结对象或软/弱/幻像引用触发额外的异步活动。此类活动必然是异步的,并且可能运行无限长的时间。Runtime.gc()不会等待完成。这实际上是一个定义问题:如果终结器和引用队列尚未处理,您是否认为 GC 是“完成”的?
没有什么真正强制上面的代码终止......
对于“更完整”的 GC,您可以使用 JVMTI 接口(调试器使用的接口),它允许您运行 GC,但也可以暂停目标 JVM 线程,这使得定义和实现“完整 GC”变得更加容易“ 状态。