1.类信息存放在方法区(元空间中)
ClassInfoTests a = new ClassInfoTests();
ClassInfoTests b = new ClassInfoTests();
/**
* 两个对象的地址不一致,所以a==b返回false
*/
System.out.println(a==b);
/**
* 由于两个类的class信息都在方法区(元空间),所以下面返回true
*/
System.out.println(a.getClass()==b.getClass());
2.变量信息存放在栈中,对象存储在堆中,intern可以将堆中信息挪到常量池中
/**
* s1和s2都属于临时变量,存储在栈中
* "abc"属于字符串常量,存储在的常量池中
*/
String s1 ="abc";
String s2 = "abc";
/**
* s1==s2 返回true,因为他们比较的是同一块常量池内的地址
*/
System.out.println(s1 == s2);
/**
* s3存储在栈中,new String对象是存储在堆中
* s3==s1 返回false,因为他们的地址不一样
*/
String s3 = new String("abc");
System.out.println(s3 == s1);
/**
* 使用了intern方法后,相当于把堆中的数据移动到常量池中,常量池相当于hashset,有相同的会覆盖
* 所以s3.intern() == s1 返回true
*/
System.out.println(s3.intern() == s1);
3.常量的存放位置
常量:定义一个固定值,包括:
class静态常量池
class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池(constant pool table),用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)。
字面量:如文本字符串、被声明为final的常量值等;
符号引用:类和接口的权限定名、字段的名称和描述符、方法的名称和描述符。
运行时常量池
将class文件中的常量池载入到内存中,并保存在元空间中,我们常说的常量池,就是指方法区中的运行时常量池。
字符串常量池 String a="a";
JVM 在运行时使用的全局的 StringTable(就是一个哈希表)。Hotspot 从 Java 7 开始,存放于堆里。
字节码常量池如何查看
Javap -c -v class文件地址
a.字符串常量池放在jvm什么区域
JDK1.6和以前常量池放入方法区(永久区)
JDK1.7常量池放入堆中
JDK1.8只将字符串常量池放入堆中,其他常量池放入元空间
b.字符串的"+"会直接合并,对象的"+"会转为StringBuilder
String s1 = "a";
String s2 = "b";
String s3 = "a" + "b";
String s4 = s1 + s2;
c.非字符串常量直接放在栈的临时变量表中
4.方法执行操作时序图
public void add() {
int a = 1;
int b = 1;
int c = a * b;
}
使用javap –c XXX.class进行汇编后,得到的add方法指令如下:
public void add();
Code:
0: iconst_1
1: istore_1
2: iconst_1
3: istore_2
4: iload_1
5: iload_2
6: imul
7: istore_3
8: return
栈操作时序图