我遵循了来自不同来源的一些示例,并且具有以下片段:
private void registerForMemUsageChanges() {
List<GarbageCollectorMXBean> garbageCollectorMXBeans = ManagementFactory.getGarbageCollectorMXBeans();
for (GarbageCollectorMXBean garbageCollectorMXBean : garbageCollectorMXBeans) {
listenForGarbageCollectionOn(garbageCollectorMXBean);
}
}
private void listenForGarbageCollectionOn(GarbageCollectorMXBean garbageCollectorMXBean) {
NotificationEmitter notificationEmitter = (NotificationEmitter) garbageCollectorMXBean;
GarbageListener listener = new GarbageListener();
notificationEmitter.addNotificationListener(listener, null, null);
}
public class GarbageListener implements NotificationListener {
@Override
public void handleNotification(Notification notification, Object handback) {
if (notification.getType().equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) {
doSomthing();//irrelevant
}
}
}
我添加了一个测试,该测试可以执行以下操作(同样,根据我发现的示例),并且似乎可以正常工作:
private void triggerGc() throws InterruptedException {
Object obj = new Object();
WeakReference ref = new WeakReference<Object>(obj);
obj = null;
while(ref.get() != null) {
System.gc();
}
}
在调试模式下运行时,我看到侦听器已注册到ps markweep和ps scavenge。 while循环结束(我认为已执行GC),但未调用任何通知。不是GC通知或任何类型的通知。
是侦听器注册错误还是未真正执行GC的问题?在while循环之后,弱引用似乎确实为空。
我正在使用openjdk 1.8.0_144。
答案 0 :(得分:0)
这是System.gc() javadoc所说的
调用gc方法表明Java虚拟机已消耗 努力回收未使用的对象以制造内存 它们目前可用于快速重用。控制权返回时 从方法调用来看,Java虚拟机已尽力而为 从所有丢弃的对象中回收空间。
调用垃圾收集器并不意味着将在调用时立即收集垃圾。但是通过调用gc,您只能建议JVM收集垃圾,而不能强制垃圾。
答案 1 :(得分:0)
问题实际上是: A)正如Holger在评论中提到的那样,我只是收到了影响到老一代的GC的通知,并且 B)尽管代码已经执行了,但调试器并没有在我的断点处停止,所以即使我不知道,doSomething实际上也做了一些事情。