我在卸载类时遇到了类似的情况。
我正在使用几个类加载器来模拟 JUnit 测试中的多个 JVM(这通常用于与 Oracle Coherence 集群一起使用,但我也成功地使用这种技术在 JVM 中启动了多节点 HBase/Hadoop 集群)。
由于各种原因,测试可能需要重新启动这种“虚拟”JVM,这意味着放弃旧的 ClassLoader 并创建新的 ClassLoader。
如果您进行 Full GC,有时 JVM 会延迟类卸载事件,这会导致以后出现各种问题。
我发现一种对强制 JVM 收集 PermSpace 很有用的技术如下。
public static void forcePermSpaceGC(double factor) {
if (PERM_SPACE_MBEAN == null) {
// probably not a HotSpot JVM
return;
}
else {
double f = ((double)getPermSpaceUsage()) / getPermSpaceLimit();
if (f > factor) {
List<String> bloat = new ArrayList<String>();
int spree = 0;
int n = 0;
while(spree < 5) {
try {
byte[] b = new byte[1 << 20];
Arrays.fill(b, (byte)('A' + ++n));
bloat.add(new String(b).intern());
spree = 0;
}
catch(OutOfMemoryError e) {
++spree;
System.gc();
}
}
return;
}
}
}
完整的源代码
我正在使用 String 填充 PermSpace,intern()
直到 JVM 收集它们。
但
- 我正在使用该技术进行测试
- 硬件/JVM版本的各种组合可能需要不同的阈值,因此重启整个JVM通常比强制它正确收集所有垃圾更快