方法区
主要包含三部分:
- 1、类的元信息(InstanceKlass):保存了所有类的基本信息
- 2、运行时常量池:保存了字节码文件中的常量池内容
- 3、字符串常量池:保存了字符串常量
JDK1.8中字符串常量池和运行时常量池逻辑上属于方法区,但是实际存放在堆内存中,因此既可以说两者存放在堆中,也可以说两则存在于方法区中,这就是造成误解的地方。
JDK7及之前的版本将方法区存放在堆区域中的永久代空间,堆的大小由虚拟机参数来控制。
JDK8及之后的版本将方法区存放在元空间中,元空间位于操作系统维护的直接内存中,默认情况下只要不超过操作系统承受的上限,可以一直分配。
JDK7将方法区存放在堆区域中的永久代空间,堆的大小由虚拟机参数-xx:MaxPermsize=值来控制。
JDK8将方法区存放在元空间中,元空间位于操作系统维护的直接内存中,默认情况下只要不超过操作系统承受的上限,可以一直分配。可以使用-xx:MaxMetaspacesize=值将元空间最大大小进行限制。
字符串常量池
字符串常量池和运行时常量池有什么关系?
早期设计时,字符串常量池是属于运行时常量池的一部分,他们存储的位置也是一致的。
后续做出了调整将字符串常量池和运行时常量池做了拆分。
1 | public static void main(string[] args){ |
输出false String d = a + b; 实际上是用StringBuilder创建了一个新对象”12”在堆内存中 而c是字符串常量池中的 所以不相等
1 | public static void main(string[] args){ |
输出true 常量 编译时期直接连接