JVM

JVM内存模型

2020-07-24  本文已影响0人  吃火锅只蘸麻酱

视频讲解:https://www.bilibili.com/video/BV16J411h7Rd?p=21

JVM内存模型非常好的总结帖:https://mp.weixin.qq.com/s/lryDeCfiacRxCMpzEmyoLA

方法区与常量池

方法区存着类的信息,常量和静态变量,即类被编译后的数据。这个说法其实是没问题的,只是太笼统了。更加详细一点的说法是方法区里存放着类的版本,字段,方法,接口和常量池。常量池里存储着字面量和符号引用(类的全限定名、字段名和属性、方法名和属性)。

class文件信息,class文件常量池和运行时常量池的关系
常量池内容
静态常量池和动态常量池的关系以及区别
静态常量池存储的是当class文件被java虚拟机编译后存放在方法区的一些字面量和符号引用,字面量包括字符串,基本类型的常量,符号引用其实引用的就是常量池里面的字符串,但符号引用不是直接存储字符串,而是存储字符串在常量池里的索引。
动态常量池是当class文件被加载完成后,java虚拟机会将静态常量池里的内容转移到动态常量池里,在静态常量池的符号引用有一部分是会被转变为直接引用的,比如说类的静态方法或私有方法,实例构造方法,父类方法,这是因为这些方法不能被重写其他版本,所以能在加载的时候就可以将符号引用转变为直接引用,而其他的一些方法是在这个方法被第一次调用的时候才会将符号引用转变为直接引用的。
总结
方法区里存储着class文件的信息和动态常量池,class文件的信息包括类信息和静态常量池。可以将类的信息是对class文件内容的一个框架,里面具体的内容通过常量池来存储。
动态常量池里的内容除了是静态常量池里的内容外,还将静态常量池里的符号引用转变为直接引用,而且动态常量池里的内容是能动态添加的。例如调用String的intern方法就能将string的值添加到String常量池中,这里String常量池是包含在动态常量池里的,但在jdk1.8后,将String常量池放到了堆中。

String与常量池

String 类型的常量池比较特殊。它的主要使用方法有两种:

String s1 = new String("计算机");
String s2 = s1.intern();
String s3 = "计算机";
System.out.println(s2);//计算机
System.out.println(s1 == s2);//false,因为一个是堆内存中的String对象一个是常量池中的String对象,
System.out.println(s3 == s2);//true,因为两个都是常量池中的String对象

java堆中对象探秘

对象的创建方法:指针碰撞、空闲列表
对象的内存布局

对象在堆内存中可以划分为三个部分:对象头、实例数据和对齐填充

对象的访问定位

主流的访问方式主要有两种:句柄、直接指针

这两种方式各有优势,使用句柄来访问的最大好处就是reference中存储的是稳定句柄地址,在对象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而reference本身不需要修改;使用直接指针来访问的最大好处就是速度快,它节省了一次指针定位的时间开销,由于对象访问在java中非常频繁,因此这类开销积少成多就是一项极为可观的执行成本。

上一篇 下一篇

猜你喜欢

热点阅读