JVM-方法区

方法区

主要包含三部分:

  • 1、类的元信息(InstanceKlass):保存了所有类的基本信息
  • 2、运行时常量池:保存了字节码文件中的常量池内容
  • 3、字符串常量池:保存了字符串常量

JDK1.8中字符串常量池和运行时常量池逻辑上属于方法区,但是实际存放在堆内存中,因此既可以说两者存放在堆中,也可以说两则存在于方法区中,这就是造成误解的地方。

JDK7及之前的版本将方法区存放在堆区域中的永久代空间,堆的大小由虚拟机参数来控制。
JDK8及之后的版本将方法区存放在元空间中,元空间位于操作系统维护的直接内存中,默认情况下只要不超过操作系统承受的上限,可以一直分配。

JDK7将方法区存放在堆区域中的永久代空间,堆的大小由虚拟机参数-xx:MaxPermsize=值来控制。
JDK8将方法区存放在元空间中,元空间位于操作系统维护的直接内存中,默认情况下只要不超过操作系统承受的上限,可以一直分配。可以使用-xx:MaxMetaspacesize=值将元空间最大大小进行限制。

字符串常量池

字符串常量池和运行时常量池有什么关系?
早期设计时,字符串常量池是属于运行时常量池的一部分,他们存储的位置也是一致的。
后续做出了调整将字符串常量池和运行时常量池做了拆分。

1
2
3
4
5
6
7
public static void main(string[] args){
String a="1";
String b="2";
String c="12";
String d = a + b;
System.out.printin(c == d); //false
}

输出false String d = a + b; 实际上是用StringBuilder创建了一个新对象”12”在堆内存中 而c是字符串常量池中的 所以不相等

1
2
3
4
5
public static void main(string[] args){
String c="12";
String d = "1"+"2";
System.out.printin(c == d); //true
}

输出true 常量 编译时期直接连接