【问题标题】:PermGen space of heapPermGen 堆空间
【发布时间】:2013-11-21 11:17:25
【问题描述】:

image所示,Permgen又进一步分为几个部分。

运行时常量池存储与类加载器加载的每种类型相关的常量。

方法区存放方法返回类型、方法名称等方法信息。 (如果我在这里错了,请纠正我。

Reserved area是permgen需要更多内存时保留的部分。

但我不明白的是,图像中的代码区域是什么?任何代码都存储在这个空间中(对我来说似乎很模糊)?

【问题讨论】:

  • 仅供参考:在 JDK 8 中删除了 PermGen:PermGen elimination in jdk 8
  • @Batty 能否请您添加图表源的链接?
  • @Yaneeve 来源已添加。
  • @AndreyChaschev 信息丰富 :)
  • @AndreyChaschev ... 替换为 Metaspace,非常相似

标签: java permgen


【解决方案1】:
Any code is stored in this space(seems vague to me)?

有什么具体原因吗?

可能的答案可能是:代码区存储加载到内存中的类的字节码。

但是问题来了,为什么类不直接加载到 RAM 中?

因为我们有一个 JVM 来提供互操作性,由于 JVM 是 java 代码和机器之间的中介,我们需要一些地方来存储代码语句,直到 JVM 被 OS 调度来执行它的代码。(对于 OS JVM 是一个过程)。因此,它将字节代码加载到代码区域(如果我是对的),并在计划时进一步将代码(.class)解释为底层机器指令。

对我的回答是“代码区保存类的字节码”。

为了支持上面提到的想法,这里有一些概念是从Oracle blog复制过来的,上面写着:

因此,Java 类存储在永久代中。什么都 这需要吗?除了 Java 类的基本字段之外,还有:

  1. 类的方法(包括字节码)
  2. 类的名称(以对象的形式在永久代中也指向一个字符串)
  3. 常量池信息(从类文件中读取的数据,所有详细信息请参见 JVM 规范的第 4 章)。
  4. 与类关联的对象数组和类型数组(例如,包含对方法的引用的对象数组)。
  5. JVM 创建的内部对象(例如 java/lang/Object 或 java/lang/exception)
  6. 编译器 (JIT) 用于优化的信息

希望它清除。

【讨论】:

  • 你确定,代码放在这里?因为如果所有代码都放在这里,我认为 64MB 的 permgen 是不够的。再想一想。 :)
  • 根据Java Language Specs,其中一个运行时数据区是方法区,其中保存了方法代码、构造函数代码、方法数据和运行时常量水池。所以在你分享的图片中,我觉得方法区域被分成三个部分只是为了可视化目的。并且代码包含您的类代码(构造函数和方法语句)。 大约 64 MB permgen 空间? permgen 的最大大小有限制吗?
【解决方案2】:

来自一篇关于 PermGen 问题的有趣文章:Will Java 8 Solve PermGen OutOfMemoryError?

Oracle 的 JVM 开发人员 Jon Masamitsu 在他的博客中解释了 2006 永久代的目的:永久代包含 关于类的信息,例如字节码、名称和 JIT 信息。它存储在一个单独的空间中,因为它主要是 静态和垃圾收集可以通过分离得到更好的优化 它。

【讨论】:

    【解决方案3】:

    实际上 PermGen 存储了你所有的静态代码。我认为这对你来说是有道理的,为什么 PermGen 中有一个代码区域。

    【讨论】:

      【解决方案4】:

      我会冒昧猜测,根据 Jon Masamitsu 的以下 article,以下引述摘自,上面的数字是虚假陈述(或改写 - 一种误导性的表述):

      因此,Java 类存储在永久代中。什么都 这需要吗?除了 Java 类的基本字段之外,还有

      类的方法(包括字节码)

      类的名称(在 指向字符串的对象的形式也在永久中 一代)

      常量池信息(从类文件中读取的数据, 有关所有详细信息,请参阅 JVM 规范的第 4 章)。

      对象 与类关联的数组和类型数组(例如,对象数组 包含对方法的引用)。

      JVM 创建的内部对象 (例如 java/lang/Object 或 java/lang/exception)

      信息 用于编译器 (JIT) 的优化

      【讨论】:

      • 不,我的意思是,据我所知,上图中应该有一个正方形/矩形/区域,用于六种实体类型中的每一种 + 用于保留空间的实体类型。但同样,我不确定,也无法确定更多。此外,这可能与热点更相关,而不是另一个 JVM 实现
      【解决方案5】:

      解析的所有类的字节码都存在于 permgen 中。仅仅因为一个库有 1.2MB 的类,它们不会被 JVM 从 JAR 加载。有可能,甚至很可能,这些类中只有一小部分被特定应用程序使用。

      仅使用 64MB permgen,您就可以运行许多总 JAR 大小大于 1GB 的大型应用程序服务器,因为只有一小部分类被使用过。

      也举这个例子:

      class A {
         // ... code
      }
      
      class B {
         void method1() {
            // something
         }
      
         void method2() {
            A a = new A();
         }
      }
      

      虽然这些类可能驻留在同一个 JAR 中,但仅创建 B 的实例不会导致加载类 A。如果您从不调用method2(),则JVM 将永远不会加载A 类。此外,与普遍的看法相反,permgen 可以被垃圾回收,如果空间变小,并且堆上没有实例引用class A,则可以从 permgen 中删除 A 类。

      【讨论】:

        猜你喜欢
        • 2011-09-04
        • 2013-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-31
        相关资源
        最近更新 更多