如image所示,Permgen进一步分为几个部分。
运行时常量池存储与类加载器加载的每种类型相关的常量。
方法区域存储方法返回类型,方法名称等方法信息。 (如果我在这里错了,请纠正我。)
如果permgen需要更多内存,保留区域是保留的部分。
但我不明白的是,图片中的代码区域是什么?任何代码都存储在这个空间中(对我来说似乎含糊不清)?
答案 0 :(得分:2)
Any code is stored in this space(seems vague to me)?
有什么具体原因吗?
可能的答案可能是:代码区存储加载到内存中的类的字节代码。
但问题来了,为什么类没有直接加载到RAM中?
因为我们有一个JVM来提供互操作性,因为JVM是java代码和机器之间的中介,我们需要一些地方来存储代码语句,直到操作系统调度JVM来执行其代码。(对于OS JVM是一个处理)。因此,它在代码区域中加载字节代码(如果我是正确的),并且在调度时,进一步将代码(.class)解释为底层机器指令。
对我的回答是“代码区域保存了类的字节代码”。
为了支持上面提到的想法。这里有一些概念被复制,因为它来自Oracle blog,其中说:
因此Java类存储在永久代中。什么都有 这需要吗?除了Java类的基本字段外,还有:
- 类的方法(包括字节码)
- 类的名称(以永久代中也指向字符串的对象形式)
- 常量池信息(从类文件读取的数据,有关所有详细信息,请参阅JVM规范的第4章)。
- 与类关联的对象数组和类型数组(例如,包含对方法的引用的对象数组)。
- JVM创建的内部对象(例如java / lang / Object或java / lang / exception)
- 编译器(JIT)用于优化的信息
醇>
希望它能够清除。
答案 1 :(得分:0)
来自一篇关于PermGen问题的有趣文章:Will Java 8 Solve PermGen OutOfMemoryError?:
Oracle的JVM开发人员Jon Masamitsu在他的博客中解释了2006年 永久世代的目的:永久世代包含 有关类的信息,例如字节码,名称和JIT 信息即可。它存储在一个单独的空间中,因为它主要是 通过分离可以更加优化静态和垃圾收集 它
答案 2 :(得分:0)
实际上PermGen存储了所有静态代码。我认为这对你来说是有意义的,为什么PermGen中有代码区。
答案 3 :(得分:0)
我将根据以下article冒充 猜 ,由Jon Masamitsu提出以下引用,上图为虚假陈述(或改写 - 误导性陈述):
因此Java类存储在永久代中。什么都有 这需要吗?除了Java类的基本字段外还有
类的方法(包括字节码)
班级名称(in 指向永久物中的字符串的对象形式 一代)
常量池信息(从类文件中读取的数据, 有关所有详细信息,请参阅JVM规范的第4章)。
对象 与类关联的数组和类型数组(例如,对象数组 包含对方法的引用。)
JVM创建的内部对象 (例如java / lang / Object或java / lang / exception)
信息 用于编译器(JIT)的优化
答案 4 :(得分: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
,则可以从PermGen的。