Java 核心技术

JVM基础-对象在jvm中存储及方法操作演示

2020-12-06  本文已影响0人  迦叶_金色的人生_荣耀而又辉煌

上一篇 <<<JVM基础-内存结构
下一篇 >>>


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);
intern方法执行前的效果
intern方法执行后的效果

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
栈操作时序图
反汇编指令请参考JVM-反汇编指令手册
对象的布局请参考Java基础-对象布局
上一篇下一篇

猜你喜欢

热点阅读