JVM YoungGen 0%,Perm Gen 99%,OldGen Full

时间:2016-05-14 20:13:22

标签: java garbage-collection jvm heap-memory

我有一个JEE应用程序,最近开始看到CPU使用率的峰值(例如,40核心服务器上的27个核心的100%)以及应用程序不可用的时间越来越长。它与下一篇文章中描述的问题非常相似,包括弹跳应用程序服务器使问题消失直到几小时后再次出现的事实:

Old Gen heap is full and the Eden and Survivor are low and almost empty

当应用程序遇到这些"冻结时,我已经采取了一些核心转储输出。我看到以下JVM GC输出:

PSYoungGen total 11221504K, used 2435K
eden space 9238528K, 0% used
from space 19829796K, 0% used
to space 1970176K, 0% used
ParOldGen total 39613440K, used 39276477K
object space 39613440K, 99% used
PSPermGen total 254976K, used 115497K
object space 254976K, 45% used

基于引用的帖子和上面的输出,我想我明白了"冻结"是否被ParOldGen空间上的垃圾收集器驱动(徒劳?)。我缺少的部分:

  1. 为什么PermGen空间保持在45%的使用率。也就是说,ParOldGen中~39GB的东西最终会转变为PSPermGen吗?

  2. 几乎空的PSYoungGen空间有什么意义?这是否意味着应用程序不能在稳定状态下创建任何/许多新对象实例?

  3. 上面的帖子还描述了"提供更多余量的选项"到ParOldGen,但我不清楚这是否意味着通过-Xmx增加总堆大小,或者是否有明确的JVM GC参数。我看到NewRatio参数控制了年轻一代相对于老一代的规模。 PSYoungGen基本上是空的这一事实是否意味着它太大了,我应该使用更小的NewRatio值?

    提前感谢您的任何帮助。

2 个答案:

答案 0 :(得分:1)

  

ParOldGen中~39GB的东西最终会转变为PSPermGen吗?

Java 7中的PermGen(在Java 8中用metaspace替换)用于保存代码。从堆传递到PermGen的唯一事情是字节代码,因此除非您生成或加载类,否则任何东西都不会从一个传递到另一个。它们是不同的空间。

  

几乎空的PSYoungGen空间有什么意义?

完整的GC后,年轻的一代是空的。一旦你的老一代开始填补,完整的GC很常见。

  

这是否意味着应用程序不能在稳定状态下创建任何/许多新对象实例?

更有可能意味着它最近已经完成GC-ed。

  

描述了"提供更多余量的选项"到ParOldGen,但我不清楚这是否意味着通过-Xmx增加总堆大小,或者是否有明确的JVM GC参数。

增加最大堆可以给你更大的空间,但我会先检查

  • 你没有内存泄漏。
  • 您无法将大部分数据从堆中移出,例如数据库或本机内存。
  

PSYoungGen基本上是空的这个事实是否意味着它太大了,我应该使用更小的NewRatio值?

这可能会为旧版本提供更多空间,但它可能会在内存耗尽之前给你更多时间。

答案 1 :(得分:0)

  

为什么PermGen空间保持在45%的使用率。也就是说,ParOldGen中的~39GB内容最终是否会转换为PSPermGen?

没有。 OldGen&无法共享PermGen个空格。 PSPermGen主要包含PermGen空间中类加载器加载的类。 ParOldGen包含长期存在的对象的堆内存。

在JDK 1.8中,PermGen已被Metaspace取代。有关详细信息,请参阅此article

有关详细信息,请参阅以下SE问题:

Java heap terminology: young, old and permanent generations?

  

几乎空的PSYoungGen空间有什么意义?这是否意味着应用程序不能在稳定状态下创建任何/许多新对象实例?

@Peter Lawrey已正确回答。在Full GC之后,YoungGen几乎是空的=> 您没有在应用程序中累积来自短期对象的垃圾

  

上面的帖子还描述了"提供更多余量的选项"到ParOldGen,但我不清楚这是否意味着通过-Xmx增加总堆大小,或者是否有明确的JVM GC参数。

您的旧代已完全意味着您的应用程序正在保留来自长期存在的对象的堆。

现在,您必须使用visualvmMAT等分析工具检查应用程序中可能的内存泄漏(如果有)

如果您没有内存泄漏,可以使用-Xmx增加堆大小。

  

PSYoungGen基本上是空的这个事实是否意味着它太大了,我应该使用更小的NewRatio值?

由于您使用的是更大的堆,我建议您使用G1GC算法。如果使用G1GC算法,则不要自定义默认值,因为G1GC算法会处理更好的堆管理。

查看关于G1GC转换(Complete List of G1 GC Switches部分),Use Cases文章和相关SE问题的oracle文章:

Java 7 (JDK 7) garbage collection and documentation on G1