为什么运行堆转储会导致我的线程计数大幅下降?

时间:2013-08-01 18:23:06

标签: java memory-leaks

这可能是一个天真的问题。我正在调查我的应用程序中可能的内存泄漏。我一直在通过jvisualvm监控tomcat进程。有一次我选择了堆转储。

我很惊讶地看到我的线程计数,并且在生成堆转储后内存消耗显着下降。参考以下屏幕截图。

Threads Memory

为什么我的线程计数和内存因堆转储而丢失?

[编辑]为了回应关于它做出完整垃圾收集以响应堆转储的答案,我的后续问题是,垃圾收集不应该一直发生吗?我没有看到先前的戏剧性下降,只是GC正常发生的常规下降。这个GC循环与正常情况有什么不同?

3 个答案:

答案 0 :(得分:2)

在转储之前,您的程序处于稳定状态,包括:

  1. 分配短期对象;
  2. 发生了一次小型GC,将它们全部清除。
  3. 与此同时,周围有很多无法到达的物品,属于终身一代。

    然后你做了线程转储。此操作本身会占用大量内存,因此会发生 major 集合。这抹去了你的终身物品。

    现在,这些对象可能已经运行了终结器,或者它们可能与某些软引用有关,并且为了响应它们的收集/完成,许多线程已经结束。

    这导致堆分配斜率(每秒分配的字节数)变得非常平坦。

答案 1 :(得分:1)

堆转储可能会在写出堆之前触发完整的垃圾收集。

答案 2 :(得分:1)

当您触发堆转储时,您还会触发完整集合。当没有强引用的资源消失时,可以停止一些守护程序线程。