前言:看这本书,当不了解jvm虚拟机的时候,遇到一些不理解的概念,可以先跳过,在后面都会有补充。本章概括,仅自己阅读书籍完成第一遍的时候的一些收获和观点,不一定正确,要是朋友们发现有理解错误的地方,希望在评论区予以指正。会持续更新,完善,修改
jvm运行时数据区域
主要内容:jvm的内存分区以及各个区域的作用(这块主要涉及到java代码如何转换成字节码,以及各个分区存放的各种字节码相关的信息),以及各个分区是否线程私有(这块只要涉及到并发以及工作内存和主内存交互相关逻辑)
如何理解更加深刻:自己写一段代码,使用工具,将其编译成字节码。查看字节码,结合代码来加深理解。
程序计数器
主要是记录程序运行的行数
虚拟机栈
有栈帧这一基本结构构成,栈帧包含了
- 局部变量表(这个局部变量表包含了什么,需要拓展了解)
- 基础类型
- 对象引用(有两种实现方式方式:在hotspot中,是一个指针,指向堆中的对象。另外一种是指向堆中的句柄,指向堆中的实际对象和方法区中的类信息)
- returnAddress 暂时没有很好的理解
- 操作数栈(当线程请求的栈深度超过操作数栈深度的时候,会报StackOverflowError;当虚拟机栈深度可以扩展,但是扩展时,无法申请到足够的内存会报OutOfMemoryError)
- 方法出口(指向调用位置?需要加强理解)
- 动态链接(不知道干啥用处)
第一次补充:动态链接主要是用于运行时动态链接,一般是指向运行时常量池的方法引用,用于描述java中一个方法对另外一个方法的引用
本地方法栈
基本上与虚拟机栈一样,是用于存储本地方法相关信息
堆
存放了对象实例以及数组(数组在后面某一章会有特殊的讲解和理解,第一次阅读,记忆不深刻),字符串常量以及静态变量
在分代回收算法的jvm虚拟机中,基本上是划分为
- 新生代(此阶段垃圾回收为minor) 注:此阶段垃圾回收是怎么执行的,需要梳理清楚
- eden空间:当eden空间满了,会触发minor GC,清理Eden空间内存(删除与GC Rootfs根节点没有关联的对象),存活的对象,移至from survivor中
- from survivor空间
- to survivor空间 第一次补充:jdk8中,是分为了eden空间,survivor1,survivor2,而eden空间又是分了诺干个TLAB:jvm会为每一个线程花分一小块内存
- 老年代(此阶段垃圾回收major gc)
老年代中一般都是存的大对象和生命周期长的对象(此处会有一个age判断年龄标准,可以通过命令设置) - 这地方有几个疑问:
- 新生代和老年代年龄判断标准,以及老年代年龄是通过哪个参数设置的
- 记得当有新生代的内存达到某个阈值的时候,可以直接写入?还是把原来的对象移入老年代
- 老年代和永久代的关系,以及老年代,永久代和方法区的关系。在jdk1.8之后,和元数据区的关系如何
方法区(jdk1.8之后,元数据,通过本地内存实现)
主要存放类信息(全类名,字段名,方法名,接口信息等),静态变量JDK1.8以后,移动到了堆内存,常量,编译后的代码(字节码?)
运行时常量池
运行时常量池是方法区的一部分,存放了类的一些信息:魔数,版本号,类全名等字面量和符号引用(顺序有严格要求)
- 字面量:应该是utf-8-content的那些
- 符号引用:方法,字段,接口,属性等符号(需要确认)