Java垃圾回收问题

发布于 2024-10-17 02:15:13 字数 744 浏览 2 评论 0原文

因此,我正在构建这个内存极其密集的 Java 应用程序,它构建了一个包含数百万个节点的树。使用方便的花花公子运行时方法来获取堆信息,我构建了一个很好的小方法来显示当前的内存使用情况,如下所示:

public void displayMemoryUsage() {
    long maxMem = Runtime.getRuntime().maxMemory();
    long freeMem = Runtime.getRuntime().freeMemory();
    long heapMem = Runtime.getRuntime().totalMemory();
    long usedMem = heapMem - freeMem;
    System.out.println("Memory used: " + (int) (usedMem * 100 / maxMem) + "%");
}

因此,为了测试它,我让树扩展了它的根节点(扩展到 2128 个子节点),并且然后扩展这些子节点中的每一个(树中总共约 400 万个节点)。内存显示已使用 11%。然后,我将树的根设置为根的子节点之一,并在此过程中删除对根的其他子节点的所有引用。理论上,这应该删除 2127/2128 个原始根的子级。我运行Java的Runtime.getRuntime().gc()方法进行强制垃圾回收,并告诉它再次显示内存使用情况。这次我得了10%。理论上,这个新的百分比不应该更像是设置新根之前的值的 0.05% 或 1/2128 吗?

有什么想法为什么它不能正确地捡垃圾吗?

So I have this extremely memory-intensive Java application I'm building, which builds a tree of millions of nodes. Using the handy dandy Runtime methods for getting heap information, I built a nice little method that displays the current memory usage, as shown below:

public void displayMemoryUsage() {
    long maxMem = Runtime.getRuntime().maxMemory();
    long freeMem = Runtime.getRuntime().freeMemory();
    long heapMem = Runtime.getRuntime().totalMemory();
    long usedMem = heapMem - freeMem;
    System.out.println("Memory used: " + (int) (usedMem * 100 / maxMem) + "%");
}

So just to test it out, I had the tree expand its root node (into 2128 children), and then expanded each one of those children (for a total of approx. 4 million nodes in the tree). The memory displays 11% used. I then set the root of the tree to be one of the root's children, and in doing so remove all references to the root's other children. Theoretically, this should remove 2127/2128 of the original root's children. I ran Java's Runtime.getRuntime().gc() method for forced garbage collection, and told it to display the memory usage again. This time, I got 10%. In theory, should this new percentage not be more like 0.05%, or 1/2128th of the value before setting the new root?

Any thoughts why it's not picking up the garbage properly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浴红衣 2024-10-24 02:15:13

System.gc(以及等效的Runtime.gc)方法是向垃圾收集器建议应该收集垃圾的建议,因此它并不是真正的一种方法“强制垃圾回收”:

来自 System.gc 方法的 Java API 规范:

运行垃圾收集器。

调用 gc 方法表明
Java虚拟机花费精力
致力于回收未使用的对象
为了让他们的记忆
目前可快速占用
重用。
* 当控制从
方法调用,Java 虚拟机
已尽最大努力回收
与所有废弃物体的空间。

(强调。)

此外,在一点技术细节上,即使确实发生了垃圾收集,请记住,除了您的程序之外,Java 虚拟机上还存在其他对象,因此将会有还有一些内存开销。

实际粗略了解树占用了多少内存的一种方法是检查创建树之前和之后的内存使用情况 - 但请注意,即使这样,在树被占用时也可能会发生一些垃圾收集。正在建设中,所以即使这也不是一个完美的衡量标准。

这里最好的选择可能是使用分析器(例如 jvisualvm(随 JDK 一起提供),实际看看有多少堆被什么东西使用了。

The System.gc (and the equivalent Runtime.gc) method is a suggestion to the garbage collector that garbage should be collected, so it not truly a way to "force garbage collection":

From the Java API Specification for the System.gc method:

Runs the garbage collector.

Calling the gc method suggests that
the Java Virtual Machine expend effort
toward recycling unused objects in
order to make the memory they
currently occupy available for quick
reuse.
* When control returns from the
method call, the Java Virtual Machine
has made a best effort to reclaim
space from all discarded objects.

(Emphasis added.)

Furthermore, on a little bit of a technicality, even if the garbage collection did take place, keep in mind that there are other objects that are present on the Java virtual machine aside from your program, so there's going to be some memory overhead from that as well.

One way to actually get a rough idea of how much memory is being occupied by your tree is to check the memory usage before and after creating your tree -- but note that even then, there may be some garbage collection taking place while your tree is being built, so even that isn't going to be a perfect metric.

Probably the best option here is to employ a profiler (such as the jvisualvm which comes with the JDK) to actually take a look at how much of the heap is being used by what.

静若繁花 2024-10-24 02:15:13

您应该尝试分析您的应用程序!

You should try to profile your application instead!

虚拟世界 2024-10-24 02:15:13
  1. 您确定任何地方都没有对已删除节点的引用吗?
  2. 您确定您在 gc() 之后等待了足够长的时间,即您是否多次建议它?
  1. Are you sure there are no references to the deleted nodes anywhere?
  2. Are you sure you waited long enough after gc() i.e. did you suggest it multiple times?
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文