程序计数器:
程序计数器是当文件生成class文件通过字节码解释器进行控制改变程序计数
器的值进行控制程序的走向,判断,循环等操作。每个线程都有自己独立的程
序技术器。互不干扰。
虚拟机栈:
每个线程都会创建独立的私有虚拟机栈,生命周期跟随线程相同。描述执行方
发的线程模型,根据创建栈帧存储局部变量表,动态连接,操作数栈,方法出口
等信息。
虚拟机栈的局部变量表:
简单分解是栈存储对象引用,堆存储对象实例,方法区(1.8后改为元数据区)存
储引用数据类型,静态变量,常量,final修饰的,和类的加载信息.局部变量表
就是通过地址值指向堆中的对象实例或者方法区中的属性进行引用
java堆:
java堆是线程共享的内存区域,用于存储对象实例。
堆内存分配:每个线程划分时内存时,会划分出线程私有的分配缓存区(TLAB),
提升内存的分配效率。
java堆可以在物理上不连续的空间中,但逻辑上是连续的。
方法区:
方法区是线程共享的内存区域,用于存储被虚拟机加载的类型、常量、静态变量、
和实时编译的代码缓存。
方法区通常被称为永久代。1.9以后方法区的数据统一迁移到元空间中了。
运行时常量池:
运行时常量池属于方法区的一部分,用于存储,类的版本、字段、方法、接口等描
述信息。还存储了常量池表,存放编译期生成的各种字面常量与符号引用。在类加
载后存储到常量池中。
运行时常量池具有动态性:运行时产生的常量也会存入到常量池中。
对象的创建:
jvm接受到new()时,首先会在常量池中看是否可以定位符号引用。是否被加载和初
始化。没有初始化,会先进行类的加载过程,对对象进行初始化。进行类加载完毕
后,为对象进行分配内存。
对象分配内存的方式:
指针碰撞:指针碰撞是指将空闲内存区域与使用的内存区域进行划分,使用指
针移动一段于对象大小相等的内存区域。
空闲列表:jvm会记录一张内存列表,存储已使用内存和可用空间内存,从列表
中找到足够大的内存分配给对象。
对象堆内存的布局:
对象在堆内存中的布局划分为,对象头,实例数据,对其填充
对象头:
自身运行时数据:
对象的哈希值,分代年龄,锁状态标志,线程持有锁,偏向线程ID,偏向时
间戳。
元数据指针:指向所属对象实例
对象访问定位:
一、句柄访问:在堆内存中划分出部分内存为句柄池,栈的引用执行句柄池引用。句柄
池再执行堆内存中的的具体的对象实例。好处:当对象位置移动后不需要重新修改栈中
的地址引用,直接修改句柄池中的地址引用。
二、直接指针:栈的地址引用直接指向堆内存中实例对象。好处:减少一次指针开销,快。
jvm对象回收判定方式
1.计数器:
计数器是通过jvm生成对象后再对象中添加的计数器,用来判定对象是否存活。
根据分代计算当新生成的对象一般是存放再新生代的eden区,对象每被引用一
次技术加一,相反计数器减一。当计数器数值达到15时对象会直接进去老年代。
(大对象是直接存放再老年代)
2.可达性表达式
通过一系列以GCRoot为根节点的对象,为起点为可以达到的对象之间建立链路
引用,表示该对象是存活的不需要进行回收,如果对象无法与GCROot根节点或
着与跟节点建立链接的对象进行连接则该对象为不可达对象,会进行一次标记
将对象存入FQueue队列中。之后GC会再次扫描FQueue中的对象如果这时该对象
与根节点或者与其他已经与根节点建立连接的对象产生关联则不会对改对象进
行回收,因为该对象以与GCROOT根节点建立连接表示该对象已经存活。否则会
被GC进行垃圾回收
GCROOT根节点对象:
1. 虚拟机栈中的对象
2. 方法区中静态属性和常量引用的对象
3. 本地方法栈中的对象
4. 被同步锁持有的对象
5. jvm内部通过class反射引用的对象,系统加载类
对象引用: 强->软->弱->虚
强引用:new Object()这种创建对象的方式为强引用。只要引用存在,GC就不会
对对象进行回收
软引用:有用非必须,被软引用的对象会在内存溢出之前进行回收。
弱引用:非必须的对象,会在下一次GC时进行回收
虚引用:无用的,当对象被回收时会收到系统通知。
方法区回收:
方法区回收的判定:
1. 类的所有的实例已被回收,堆中不存在对象的任何信息,也不会派生子类。
2. 类加载器已被回收。
3. 没有被反射引用。
垃圾回收:
分代收集:
弱分代:使用时创建,使用完毕进行GC
强分代:熬过越多次垃圾收集过程的对象就越难以消 亡。
对象分代收集:
新生代(MinorGC/YoungGC):新生代垃圾收集
老年代:(MajorGC/OldGC): 老年代收集,只有GMS有单独的老年代收集器
混合收集:G1存在
整堆收集:整个java堆和方法区收集
垃圾回收算法:
1. 标记-清除:对要回收的对象进行标记,标记后进行对象清除。效率不稳定,
容易产生垃圾碎片,频繁触发垃圾回收
2. 标记-复制:将内存划分范围相同的两个区域,当进行垃圾回收时将存活的对
象存放到另一块内存区域,将原区域的垃圾进行清理。浪费空间内存
3. 标记整理:将存活的对象进行移动,清理边界意外的内存区域。
七种垃圾收集器:
一、Serial:应用于新生代采用标记清除算法实现,老年代采用标记整理算法。
是单线程收集器,垃圾收集时,其他线程停止工作。优点;简单、高效
二、ParNew:应用于新生代采用标记复制算法实现,老年代采用标记整理算法。
是多线程收集器,可以于GMS收集器配合使用。
三、 Parallel Scavenge:基于标记复制算法,可以并行收集的多线程收集器,
可以控制吞吐量,
四、Serial Old:是Serial收集器的老年代版本,它同样是一个单线程收集器,
使用标记-整理算法。老年代采用标记整理算法
五、Parallel Old:是Parallel Scavenge收集器的老年代版本,支持多线程并
发收集,基于标记-整理算法实现。
六、GMS收集器:一种以获取最短回收停顿时间为目标的收集器。
执行步骤:
1. 初始标记:标记一下GC Roots能直接关联到的对象,速度很快;
2. 并发标记:标记与GC ROOT 直接关联的整个对象图进行遍历,耗时
较长,但可与用户程序并发执行。不需要停顿用户线程,可以与垃圾收
集线程一起并发运行
3. 重新标记:修正并发标记期间,因用户程序继续运作而导致标记产
生变动的那一部分对象的 标记记录
4. 并发清除:清理删除掉标记阶段判断的已经死亡的对象,由于不需
要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。
优点:并发收集、低停顿
缺点:
无法处理浮动垃圾:并发标记和并发清除阶段。程序运行时产生的新的
垃圾对象。当前GC无法清除,等待下次GC时清除。
GMS基于标记清除算法,会产生大量的垃圾碎片,提前触发FULL GC
七、G1收集器:称为全功能的垃圾收集器,可以面向堆内存任 何部分来组成回
收集(Collection Set,一般简称CSet)进行回收,衡量标准不再是它属于哪个
分代,而 是哪块内存中存放的垃圾数量最多,回收收益最大,这就是G1收集器
的Mixed GC模式。
执行步骤:
1. 初始标记(Initial Marking):标记一下GC Roots能直接关联到的
对象,并且修改TAMS 指针的值,让下一阶段用户线程并发运行时,能
正确地在可用的Region中分配新对象。这个阶段需要 停顿线程,但耗
时很短,而且是借用进行Minor GC的时候同步完成的,所以G1收集器在
这个阶段实际 并没有额外的停顿。 ·
2. 并发标记(Concurrent Marking):从GC Root开始对堆中对象进行
可达性分析,递归扫描整个堆里的对象图,找出要回收的对象,这阶段
耗时较长,但可与用户程序并发执行。当对象图扫描完成以后,还要重新
处理SATB记录下的在并发时有引用变动的对象。 ·
3. 最终标记(Final Marking):对用户线程做另一个短暂的暂停,用于
处理并发阶段结束后仍遗留 下来的最后那少量的SATB记录。
4. 筛选回收(Live Data Counting and Evacuation):负责更新Region的
统计数据,对各个Region的回 收价值和成本进行排序,根据用户所期望的
停顿时间来制定回收计划,可以自由选择任意多个Region 构成回收集,然
后把决定回收的那一部分Region的存活对象复制到空的Region中,再清理掉
整个旧 Region的全部空间。这里的操作涉及存活对象的移动,是必须暂停用户
线程,由多条收集器线程并行完成
G1收集器不再区分eden区,suriver区,或老年代,而是把4整个堆划分为相同大小
的Region区,每个区都可以作为不同的分代区进行替换。humongous为单独大大对象
存储区域,当对象所占空间超过region区的一半即为大对象存储到N个连续的。
G1不再单独区分分代区域,但保留分代概念。为一系列Region内存区域构成的不连续
的动态集合。
humongous region区。
优点: 延迟可控时尽可能的获取高的吞吐量
八、Shenandoah收集器
为redhat开发的一款收集器,只能在openjdk中提供。不作为oraclejdk官方jdk。
shenandoah收集器为低延迟收集器。
执行步骤:
1.初始标记: 标记与GCROOT直接关联的对象,仍会线程停顿,与堆得大小无关,
只与GCROOT数量相关。
2. 并发标记: 遍历与GC ROOT直接关联的整个对象图。
3. 最终标记:段统计出回收价值 最高的Region,将这些Region构成一组回收
集(Collection Set)。最终标记阶段也会有一小段短暂的停 顿
4. 并发清理:清理region中没有任何对象存活的内存区域。
5. 并发回收:将存活的对象复制到空的region内存区域中
6. 初始引用更新:元对象引用修正到复制后的新地址
7. 并发引用更新:修改对象引用,旧的对象引用到新的地址值中
8. 最终引用更新:修改与GCROOT关联引用
9. 并发清理:回收无对象存活的region区域
九、ZGC收集器:并发整理算法实现
oracle研发的低延迟收集器。
同样采用region内存布局,分为大中小三种
小:固定容量为2M,用于放置小于256KB的小对象。
中:固定容量为32M,用于放置大于等于256KB但小于4MB的对象
大:容量可动态扩展,为2M的整倍数,存储4M或大于4M的对象,每个大的region只
存放一个大对象
染色指针技术:将对象染色指针信息直接标记到对象指针中。
染色指针的优点:指针信息直接记录到对象指针中,对象移动后,对象所在的region
区域会直接释放或者重置掉该区域。减少垃圾收集中的内存屏障的使用,设置。
执行步骤:
1. 并发标记:标记与GC ROOT直接关联的对象,在对象指针上标更新Marked 0和
Marked 1标记。
2. 并发预备重分配:根据特定条件统计需要清理的region区域,组成重新分配集。
3. 并发重分配:将重分配集中存活的对象分配到新的region区域。为重分配集的
region区创建一个转发表,记录新旧对象转换关系。
4. 并发重映射(Concurrent Remap):重映射所做的就是修正整个堆中指向重分
配集中旧对象的所有引用,
衡量垃圾收集器的标准:内存占用,吞吐量,延迟
对象分配:
1. 对象优先在Eden分配,空间不足时会发起一次Minor GC
2. 大对象直接进入老年代。
3. 长期存活的对象进入老年代。
4. 在Survivor空间中相同年龄所有对象大小的总和大于 Survivor空间的一半,年龄大
于或等于该年龄的对象就可以直接进入老年代