Java程序能否检测到堆空间不足?

11

我将在室友的电脑上运行一个遗传算法整个周末,我担心这么长时间会耗尽内存。不过我的算法工作方式可以相对轻松地修剪掉一些不太有用的结果,所以如果有办法在程序即将耗尽堆空间之前告诉我,我可能可以腾出空间继续运行更长时间。

在OutOfMemoryError之前是否有办法通知我当JVM快要耗尽堆空间时?


可能是如何动态监测Java堆大小?的重复问题。 - Andreas Dolk
@Andreas_D,这个问题涉及到对程序的外部监控。我希望我的程序在即将耗尽堆空间时能够做出反应。 - zneak
其他问题的答案包括内部和外部监控解决方案。 - Andreas Dolk
4个回答

8
你可以注册一个javax.management.NotificationListener,在达到某个阈值时被调用。
类似于:
final MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();
final NotificationEmitter ne = (NotificationEmitter) memBean;

ne.addNotificationListener(listener, null, null);

final List<MemoryPoolMXBean> memPools = ManagementFactory
    .getMemoryPoolMXBeans();
for (final MemoryPoolMXBean mp : memPools) {
  if (mp.isUsageThresholdSupported()) {
    final MemoryUsage mu = mp.getUsage();
    final long max = mu.getMax();
    final long alert = (max * threshold) / 100;
    mp.setUsageThreshold(alert);

  }
}

这里的listener是你自己实现的NotificationListener。


那看起来很像我想要的。我会试一试。 - zneak
1
如果您需要一个例子,我在http://code.google.com/p/pitestrunner/中使用了这种方法。查找MemoryWatchdog类及其在MutationTestSlave中的使用。 - henry
在订阅时不要忘记添加过滤器,例如:NotificationFilter filter = x -> MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED.equals(x.getType()); ne.addNotificationListener(tryPreventOom, filter, null); - Sergey Karpushin

3
您可以尝试这个:
// Get current size of heap in bytes
long heapSize = Runtime.getRuntime().totalMemory();

// Get maximum size of heap in bytes. The heap cannot grow beyond this size.
// Any attempt will result in an OutOfMemoryException.
long heapMaxSize = Runtime.getRuntime().maxMemory();

// Get amount of free memory within the heap in bytes. This size will increase
// after garbage collection and decrease as new objects are created.
long heapFreeSize = Runtime.getRuntime().freeMemory();

在这里找到 - http://www.exampledepot.com/egs/java.lang/GetHeapSize.html

(该链接介绍了如何在Java中获取堆大小的方法)

我想这可能可以成为一个不错的hack,但我更愿意在达到某个阈值时自动收到通知,而不是必须在给定间隔内轮询内存状态(有点像iOS上的内存通知)。 - zneak
除非你自己编写一个轮询程序在后台执行,否则我不知道还有其他方法可以根据给定的阈值自动通知。 - Nikhil

2

只需使用WeakReferences来处理可丢弃的结果,这样如果出于空间原因需要丢弃它们,它们就会被丢弃。


我不能把它交给垃圾回收器自行决定,因为我需要在决定可删除对象之前对其进行审查。 - zneak
或者使用较长寿命的SoftReferences,WeakReference总是在GC时被丢弃。您可以保留一个ReferenceQueue以便通知可能被清理的对象。 - Peter Lawrey

0

我不确定,但是JConsole不能解决你的目的吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接