Start with JVM
周志明先生著-《深入理解Java虚拟机》,书买回来好几天了,但是最近才准备开始搞一搞了(哭瞎…..)。首先是第一章的Java以及JVM发展历史,大概知道了现行的应用最广泛的Java虚拟机是HotSpot,当然一些商业公司也有使用自己的虚拟机。
JVM运行时数据区
这是放在Java内存区域与内存溢出异常里面的必备知识,描述了Java虚拟机在运行时的数据区域
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
私有
- 程序计数器:记录当前线程所执行字节码的行号指示器
- 虚拟机栈:存放了当前线程调用方法的局部变量表、操作数栈、动态链接、方法返回值等信息(可以理解为线程的栈)
- 本地方法栈:为虚拟机使用的Native方法提供服务,后多与JVM Stack合并为一起
共享
- Java堆:占据了虚拟机管理内存中最大的一块(没想到吧),唯一目的就是存放对象实例(与引用是两个概念),也是垃圾回收器主要管理的地方,故又称GC堆。先开坑,后面讲垃圾回收机制再详述
- 方法区:存储加载的类信息、常量区、静态变量、JIT(即时编译器)处理后的数据等,类的信息包含类的版本、字段、方法、接口等信息。需要注意是常量池就在方法区中,也是我们这次需要关注的地方。
提一下这个Native方法
指得就是Java程序调用了非Java代码,算是一种引入其它语言程序的接口
看一下方法区
方法区因为总是存放不会轻易改变的内容,故又被称之为“永久代”。HotSpot也选择把GC分代收集扩展至方法区,但也容易遇到内存溢出问题。可以选择不实现垃圾回收,但如果回收就主要涉及常量池的回收和类的卸载(这里开坑,后续补上链接)
运行时常量池
回归本次讨论正题,主要是在看Java和C++的一些原理时,老是有“常量池”这个我一知半解的讨厌的字词,烦的一批,今天我就来探一探究竟。
JVM中运行时常量池在方法区中,因为是建立在JDK1.7/1.8的基础上来研究这个,所以我先认为String常量池在堆中。Class文件中除了类的版本、字段、方法、接口等描述信息,还有常量池,用于存放编译期生成的各种字面量和符号引用
运行时常量池与Class文件常量池区别
- JVM对Class文件中每一部分的格式都有严格的要求,每一个字节用于存储那种数据都必须符合规范上的要求才会被虚拟机认可、装载和执行;但运行时常量池没有这些限制,除了保存Class文件中描述的符号引用,还会把翻译出来的直接引用也存储在运行时常量区
- 相较于Class文件常量池,运行时常量池更具动态性,在运行期间也可以将新的变量放入常量池中,而不是一定要在编译时确定的常量才能放入。最主要的运用便是String类的intern()方法
- 在方法区中,常量池有运行时常量池和Class文件常量池;但其中的内容是否完全不同,暂时还未得知
String.intern()
检查字符串常量池中是否存在String并返回池里的字符串引用;若池中不存在,则将其加入池中,并返回其引用。
这样做主要是为了避免在堆中不断地创建新的字符串对象
那class常量池呢?
具体的等分析到Class文件格式再来填这个坑,先来看常量池中的内容: