3

我正在编写一个无法在 Eclipse 中测试的 servlet,我需要在服务器上运行。我想做内存分析并查明任何泄漏。所以,我认为我需要编写可以告诉我当前内存使用情况的调试语句。有人可以向我指出有关如何执行此操作和/或 JDK 中的哪些类执行此操作的良好参考吗?

请注意,我不能使用“Eclipse MAT”。

4

5 回答 5

7

不能使用 jdk jvisualvm中的内置工具吗?

于 2011-03-18T07:21:33.443 回答
2

JConsole来拯救你!

于 2011-03-18T07:24:45.697 回答
1

所以,我认为我需要编写可以告诉我当前内存使用情况的调试语句。

这很可能对您没有太大帮助,因为垃圾收集器仅通过查看计数就很难找到内存泄漏(您并不真正知道 gc 何时运行以及它实际收集的内容,有时它不会收集一切可收藏的东西)。因此,您可能需要制作一些内存快照并对其进行分析,即查看哪些对象(或哪些类型的对象)未被收集,从而创建了越来越多的实例。

为此,请查看建议的工具(JVisualVM、JConsole)。

如果您仍想从程序内部获取内存使用信息,请尝试java.lang.management包中的类;

于 2011-03-18T07:30:57.920 回答
1

分析应用程序内存和寻找泄漏将是一项艰巨的任务,更不用说用简单的调试语句误导了。如果您不能使用远程连接到您的进程的工具,那么使用hprof将是 IMO 的一个不错的选择。此外,请查看此处的故障排除文档。

但我仍然认为,如果可能的话,如果你尝试在本地做同样的事情(即修复泄漏)会更好。

于 2011-03-18T07:31:58.460 回答
1

所以,我认为我需要编写可以告诉我当前内存使用情况的调试语句。

我想你和我一样喜欢在代码中进行分析,而不是使用 JVisualVM 或 JConsole 等外部分析工具。

您可以使用 CoralBits 的一个名为MemorySampler(由我编写)的工具,它会准确地告诉您代码内存是在哪一行分配的。下面是一个例子:

ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<String>();
MemorySampler.start();
for(int i = 0; i < strings.length; i++) queue.offer(strings[i]);
for(int i = 0; i < strings.length; i++) queue.poll();
MemorySampler.end();
if (MemorySampler.wasMemoryAllocated()) MemorySampler.printSituation();

为您提供以下输出:

Memory allocated on last pass: 24576
Memory allocated total: 24576

Stack Trace:
    java.util.concurrent.ConcurrentLinkedQueue.offer(ConcurrentLinkedQueue.java:327)
    TestGC.main(TestGC2.java:25)

现在,如果您转到ConcurrentLinkedQueue源代码的第 327 行,您将看到它在Node那里分配了一个实例。

免责声明:我是 CoralBits 的开发者之一。

于 2014-06-18T07:19:35.973 回答