堆的PermGen空间

4

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

enter image description here

运行时常量池存储与每个类加载器加载的类型相关的常量。 方法区存储方法信息,例如方法返回类型、方法名称。(如果我在这里有误,请纠正我。) 保留区是为永久代需要更多内存而保留的部分。 但我不理解的是,图像中的代码区是什么?任何代码都存储在这个空间中(对我来说似乎含糊不清)?

3
FYI:在JDK 8中已删除PermGen: JDK 8中的PermGen消除 - Andrey Chaschev
@Batty,你能否添加一个指向图表源文件的链接? - Yaneeve
@Yaneeve源代码已添加。 - codingenious
@AndreyChaschev 信息丰富 :) - codingenious
1
@AndreyChaschev...并被Metaspace所取代,后者非常相似。 - Adam Dyga
5个回答

2
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不足够。再考虑一下吧。 :) - codingenious
根据Java语言规范,运行时数据区之一是方法区,它保存方法代码、构造函数代码、方法数据和运行时常量池。因此,在您分享的图片中,我认为方法区仅为可视化目的而被分成三个部分。而代码包含了您的类代码(构造函数和方法语句)。关于64 MB的permgen空间?permgen的最大大小是否有限制? - Aman Arora

0

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

你可以运行许多大型应用服务器,其总JAR大小超过1GB,仅使用64MB permgen,因为只有其中一小部分类被使用。

还有这个例子:

class A {
   // ... code
}

class B {
   void method1() {
      // something
   }

   void method2() {
      A a = new A();
   }
}

尽管这些类可能存在于同一个JAR文件中,但仅仅创建B的实例并不会导致A类被加载。如果您从未调用method2(),那么JVM将永远不会加载A类。此外,与普遍的观点相反,permgen是可以进行垃圾回收的,如果空间变得很低,并且堆上没有引用到class A的实例,那么A类就可以从permgen中删除。


0

关于PermGen问题的有趣文章:Java 8是否解决PermGen OutOfMemoryError问题?

Oracle的JVM开发人员Jon Masamitsu在他的博客中曾在2006年解释过永久代的目的:永久代包含类的信息,例如字节码、名称和JIT信息。它存储在单独的空间中,因为它大多是静态的,并且通过分离可以更加优化垃圾回收。


0

实际上,PermGen 存储了所有静态代码。我认为这让你明白为什么 PermGen 中有一个代码区。


0

我将根据Jon Masamitsu的文章,引用以下内容,猜测上面的图表是一种错误的陈述(或者重新表述为:一种误导性的陈述):

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

类的方法(包括字节码)

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

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

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

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

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


不,我的意思是,据我所知,上面的图表中应该有一个正方形/矩形/面积表示六种实体类型和一个保留空间。但是再次强调,我不确定,并且无法得到更多信息。此外,这可能比其他JVM实现更相关于热点。 - Yaneeve

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接