Jmap堆转储,它包括年轻代吗?

发布于 2024-11-09 02:39:26 字数 639 浏览 0 评论 0原文

简单问题

jmap堆转储仅包括老年代,还是还包括年轻代?


详细解释

我有2个堆转储(jmap -heap:format=b 9999) :

  • 我的一台服务器没有负载(无 HTTP 请求),
  • 其中一台服务器使用 50% CPU,负载很高(基准测试)

现在,第一个转储显示堆大小大于第二个< /strong> (我觉得这很奇怪)。

这可能是因为年轻代(高负载)经常变化,因为垃圾收集器经常运行(是的,JVM 几乎已满)?老年代已满99%,我注意到年轻代的空间使用情况变化很大。

因此,这意味着我在 GC 完成其工作后立即进行了第二次转储,这就是它的大小较小的原因。我说得对吗?

其他信息

Java 参数:

-XX:+UseParallelGC -XX:+AggressiveHeap
-Xms2048m -Xmx4096m -XX:NewSize=64m
-XX:PermSize=64m -XX:MaxPermSize=512m

Quick question

Does the jmap heap dump include only the old generation, or also the young generation ?


Long explanation

I have 2 heap dump (jmap -heap:format=b 9999) :

  • one of my server with no load (no HTTP request)
  • one while working 50% CPU, a high load (benchmarking)

Now, the first dump shows a heap size bigger than the second (which I thought was weird).

Could that be because the Young generation (at high load) is changing often because the Garbage collector is running often (yes, the JVM is almost full) ? Old generation is full at 99%, I've noticed the young generation space usage vary a lot.

So that would mean that I made the second dump right after the GC did his job, this is why its size is smaller. Am I right ?

Additionnal informations :

Java args :

-XX:+UseParallelGC -XX:+AggressiveHeap
-Xms2048m -Xmx4096m -XX:NewSize=64m
-XX:PermSize=64m -XX:MaxPermSize=512m

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

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

发布评论

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

评论(1

可爱咩 2024-11-16 02:39:26

快速回答

两者 - 堆由年轻代和老年代组成。因此,当您进行堆转储时,内容包含两者。堆转储的统计信息应该分开。尝试删除命令的二进制部分并以纯文本形式查看它。您将看到配置摘要,然后是每一代的细分。另一方面,-histo 只会显示堆上的所有对象,没有区别

长答案

这可能是第二个进程的垃圾收集刚刚完成。或者相反,第一个进程可能有一段时间没有完整的收集并且处于较高的内存中。当您进行捕获时,该应用程序/服务器是否刚刚重新启动?如果您使用 jvisualvm 之类的工具查看空闲进程,您将看到内存分配图上下移动,即使您的进程没有执行任何工作。这只是 JVM 在做自己的事情。

通常,您的 Full GC 应该在 Old Gen 中达到 99% 标记之前就开始。JVM 将决定何时运行 Full GC。你的年轻一代会波动很大,因为这是创建/删除对象最快的地方。在完整 GC 运行之前,将进行许多部分 GC 来清理年轻代。两者之间的差异意味着 JVM 活动会暂停。看到部分 GC 不会损害您的应用程序。但是完整 GC 的暂停时间会在应用程序运行时停止它。所以你会想尽可能地减少这些。

如果您正在寻找内存泄漏或只是分析以查看应用程序 gc 的工作情况,我建议使用启动标志来打印垃圾收集统计信息。

-XX:+PrintGCDetails -verbose:gc -Xloggc:/log/path/gc.log

运行程序一段时间,然后将捕获的日志加载到工具中以帮助可视化结果。我个人使用 IBM Support Assistant Workbench 中提供的垃圾收集和内存可视化工具。它将为您提供捕获的垃圾收集统计信息的摘要以及动态图表,您可以使用它来查看应用程序中的内存的行为方式。这不会告诉您堆上有哪些对象。

在您的应用程序出现问题时,如果您可以忍受暂停,我会修改您的 jmap 命令以执行以下

jmap -dump:format=b,file=/file/location/dump.hprof <pid>

操作,使用 MAT< /a>,您将能够看到所有对象、泄漏嫌疑人以及有关堆的代、引用的各种其他统计信息。

编辑调整讨论

根据您的启动参数,您可以尝试以下几种操作

  • 将您的 -Xms 设置为等于相同的值
    作为你的-Xmx。通过这样做,JVM
    不必花时间分配
    更多的堆。如果您希望应用程序占用 4GB,请立即全部分配,
  • 具体取决于处理器的数量
    在你运行这个的系统上
    您可以为其设置标志的应用程序
    <代码>-XX:ParallelGCThreads=##。
  • 我还没试过这个,但是
    文档显示了一个参数
    -XX:+UseParallelOldGC 这显示了减少旧GC时间的一些承诺
    收藏。
  • 尝试将新一代大小更改为堆的 1/4。 (1024 而不是 64)这可能会给老一代带来太多压力。默认大小约为 30%,您将应用程序配置为为年轻一代使用约 2%。尽管您没有配置最大大小,但我担心太多数据会被移动到旧一代,因为新一代太小而无法处理所有请求。因此,您必须执行更多完整(暂停)GC 才能清理内存。

我确实相信,总的来说,如果您如此快地分配这么多内存,那么这可能是一个代问题,内存过早地分配给了老一代。如果对新一代大小的调整不起作用,那么您需要通过 -Xmx 配置添加更多堆,或者退后一步,准确查找占用内存的内容。我们之前讨论的 MAT 工具可以向您显示内存中对象的引用。我建议尝试要点 1 和 2。 4 第一。这将是您获得正确值的反复试验

Quick Answer

Both - The Heap is made up of the Young and Old Generation. So when you take a heap dump, the contents contains both. The Stats of the heap dump should be seperated. Try removing the binary portion of your command and look at it in plain text. You will see a summary of your configuration, and then a break down of each generation. On the flip side, a -histo would just show all objects on the heap with no distinction

Long Answer

It could be that a garbage collection had just finished for the 2nd process. Or the opposite, the first process may not have had a full collection in a while and was sitting at higher memory. Was this application/server just restarted when you took the capture? If you look at an idle process using a tool like jvisualvm, you will see the memory allocation graphs move up and down even though your process isn't doing any work. This is just the JVM doing its own thing.

Typically your Full GC should kick off well before it reaches a 99% mark in the Old Gen. The JVM will decide when to run the full GC. Your Young Gen will fluctuate alot as this is where objects are created/removed the fastest. There will be many partial GC's done to clean out the young gen before a full GC get run. The difference between the two will mean a pause in your JVM activity. Seeing a partial GC will not hurt your application. But the pause times of a full GC will stop your application while it runs. So you will want to minimize those the best you can.

If you are looking for memory leaks or just profiling to see how your application(s) gc is working, I would recommend using the startup flags to print the garbage collection stats.

-XX:+PrintGCDetails -verbose:gc -Xloggc:/log/path/gc.log

run your program for a while and then load the captured log in a tool to help visualize the results. I personally use the Garbage Collection and Memory Visualizer offered in the IBM Support Assistant Workbench. It will provide you with a summary of the captured garbage collection stats as well as a dynamic graph which you can use to see how the memory in your application has been behaving. This will not give you what objects were on your heap.

At problem times in your application, if you can live with a pause, I would modify your jmap command to do the following

jmap -dump:format=b,file=/file/location/dump.hprof <pid>

Using a Tool like MAT, you will be able to see all of the objects, leak suspects, and various other stats about the generations, references of the heap.

Edit For Tuning discussion

Based on your start-up parameters there are a few things you can try

  • Set your -Xms equal to the same value
    as your -Xmx. By doing this the JVM
    doesn't have to spend time allocating
    more heap. If you expect your application to take 4gb, then give it all right away
  • Depending on the number of processors
    on the system you are running this
    application you can set the flag for
    -XX:ParallelGCThreads=##.
  • I havent tried this one but the
    documentation shows a parameter for
    -XX:+UseParallelOldGC which shows some promise to reduce time of old GC
    collection.
  • Try changing your new generation size to 1/4 of the Heap. (1024 instead of 64) This could be forcing too much to the old generation. The default size is around 30%, you have your application configured to use around 2% for young gen. Though you have no max size configured, I worry that too much data would be moved to old gen because the new gen is too small to handle all of the requests. Thus you have to perform more full (paused) GC's in order to clean up the memory.

I do believe overall if you are allocating this much memory so fast, then it could be a generation problem where the memory is allocated to the Old generation prematurely. If a tweak to your new gen size doesn't work, then you need to either add more heap via the -Xmx configuration, or take a step back and find exactly what is holding onto the memory. The MAT tool which we discussed earlier can show you the references holding onto the objects in memory. I would recommend trying bullet points 1 & 4 first. This will be trial and error for you to get the right values

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文