1,元空间(方法区): 存放: 1.类的信息。2,常量,3 静态变量。4 运行时常量。
常量池:
1,定义固定值,定义好后不容易发生改变也不会被gc回收
1 class静态常量池(定义字面量,符号引用)
2, 运行时常量池
3,字符串常量池 String a="a";
误区: 字符串常量池放在jvm什么区域?
jdk1.6和以前的常量池,都是放入方法区(永久区)
jdk1.7常量池放入到堆中(不合理)
jdk1.8 只是将字符串常量池放入到堆,其他常量都是放入到元空间、
package com.taotao.jvm1.day05;
/**
*@author tom
*Date 2020/8/14 0014 8:01
*
*/
public class Test02 {
public static void main(String[] args) {
String s1="a";
String s2="b";
String s3="a"+"b";
String s4=s1+s2;
String s5="ab";
String s6=s4.intern();
System.out.println(s3==s4);
System.out.println(s3==s5);
System.out.println(s3==s6);
// ==比较地址
}
}

总结:
1 在字符串 常量池中 变量引用方式类加 底层采用StringBuilder A1+a2
String ab1=a1+b;
StringBuilder stringBuilder=new StringBuilder();
stringBuilder.append(a1);
stringBuilder.append(b);
stringBuilder.toString();
2, “a”+"b"虚拟机做优化 为"ab"
package com.taotao.jvm1.day05;
/**
*@author tom
*Date 2020/8/14 0014 8:23
*
*/
public class Test01 {
/**
* 二进制文件存放那些信息: 类的信息,局部变量表,方法信息,常量池
* @param args
*/
public static void main(String[] args) {
// System.out.println("mk");
String a1="a";
String a2="a";
String b="b";
String ab1=a1+b;
StringBuilder stringBuilder=new StringBuilder();
stringBuilder.append(a1);
stringBuilder.append(b);
stringBuilder.toString();
String ab3="a"+"b";
String ab="ab";
System.out.println(ab1==ab);
System.out.println(a1==a2);
System.out.println(ab3==ab);
//equals 比较内容值是否相等
}
}


常量池
常量池:通过一张表,虚拟机根据该常量表扎到执行的类名、方法名、
参数类型、字面量。
运行常量池:常量池存放在class字节码文件中,当该类被加载,它的常量池
信息就会放入运行时常量池。
二进制字节码(类基本信息、常量池、类的方法的定义(局部变量表)、虚拟机的指令)
常量池的分类
常量池的分类:静态常量池、字符串常量池、运行时常量池
静态常量池
我们都知道,class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池(constant pool table),用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)。 字面量就是我们所说的常量概念,如文本字符串、被声明为final的常量值等。 符号引用是一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可(它与直接引用区分一下,直接引用一般是指向方法区的本地指针,相对偏移量或是一个能间接定位到目标的句柄)。一般包括下面三类常量:
类和接口的全限定名
字段的名称和描述符
方法的名称和描述符
运行常量池
而运行时常量池,则是jvm虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在元空间中,我们常说的常量池,就是指方法区中的运行时常量池。
字符串常量池
JVM 在运行时使用的全局的 StringTable(就是一个哈希表)。Hotspot 从 Java 7 开始,存放于堆里。
String a=”a” 字符串常量池
常量池的信息都会被加载到运行时常量池中
1.常量池的中的字符串仅是符号,第一使用的时候变为对象
2.利用串池的机制,来避免重复创建字符串对象
3.字符串变量拼接原理采用StringBuilder(1.8)
4.字符串常量拼接的原理是编译器优化
5.可以使用intern方法,主动将串池中还没有的字符串对象放入串池中。
常量池到底存放那块区域
Java6和6之前,常量池是存放在方法区(永久代)中的。
Java7,将常量池是存放到了堆中。
Java8之后,取消了整个永久代区域,取而代之的是元空间。运行时常量池和静态常量池存放在元空间中,而字符串常量池依然存放在堆中。
如何查看字节码常量池

package com.taotao.jvm1.day05;
/**
*@author tom
*Date 2020/8/14 0014 8:23
*
*/
public class Test01 {
/**
* 二进制文件存放那些信息: 类的信息,局部变量表,方法信息,常量池
* @param args
*/
public static void main(String[] args) {
// System.out.println("mk");
String a1="a";
String a2="a";
String b="b";
String ab1=a1+b;
StringBuilder stringBuilder=new StringBuilder();
stringBuilder.append(a1);
stringBuilder.append(b);
stringBuilder.toString();
String ab3="a"+"b";
String ab="ab";
System.out.println(ab1==ab);
System.out.println(a1==a2);
System.out.println(ab3==ab);
//equals 比较内容值是否相等
String c1="c";//字符串常量池
String c2=new String("c");//new 对象字符串放入对内存空间中
String c3= c2.intern();//将字符串对象字符放入到字符串常量池中
System.out.println(c1==c2);
System.out.println(c1==c3);
}
}
网友评论