jvm内存模型:
堆:线程共享,该区域存放对象实例,几乎所有的实例对象都存放于此,该区域也是发生GC的区域
方法区:线程共享,jdk1.8之后改叫元空间(之前叫做永久代),该区域主要存放被虚拟机加载了的类型信息,运行时常量池,静态变量,方法信息等,元空间并不占用虚拟机内存空间,而是直接占用直接内存,JDK8字符串常量池放到堆空间,其引用指向元空间(方法区)的常量池。常量池设计就是一种缓存池,为了提高程序性能。
字符串常量池:在创建字符串常量时,会确认一下常量池是否存在该字符串,如果存在,则返回引用实例,不存在则实例化字符串并放入池中
虚拟机栈:线程私有,随着线程的创建而创建,随着线程的销毁而销毁
虚拟机栈的结构图:
局部变量表:局部变量表的基本单位是slot,该表存放编译器可以确定的数据类型:8种基本数据类型以及引用类型(还有 return 的类型),对于32位以内的数据类型,只需占据一个slot,对于64位的数据类型,则需要占据两个slot.byte、short、char在存储前被转换成int,boolean也被转换成int,0表示false,非0 表示true。long和double则占据两个Slot,虚拟机会给每个slot指定一个索引,我们可以根据索引访问slot,对于64bit的数据类型,我们只需要访问前一个slot的索引即可
slot的复用:
栈帧中的局部变量表中的槽位是可以重用的,如果一个局部变量过了其作用域,那么在其作用域之后申明的新的局部变就很有可能会复用过期局部变量的槽位,从而达到节省资源的目的。
操作数栈:我们在每次执行一次方法的时候都会创建一个空的操作数栈,写入数据就是入栈操作,读取数据就是出栈操作
动态链接:指向方法去中方法引用,以保证方法执行的正确性
方法出口
本地方法栈:线程私有,虚拟机栈管理的java层的方法及其调用,那么本地方法栈就是管理native方法的栈
程序计数器:线程私有,记录线程代码执行地址
二.GC
如何判断一个对象是否可回收?
a.引用计数法:一个对象被引用,计数器加一,引用失效,计数器减一.如果计数器为0,则视为垃圾,可被清除
问题:循环引用导致计数器失效(AB相互引用,计数器均大于0,但是AB均没用)
b.可达性分析法:GCRoot可达的子节点则视为存活对象,相应的那些从root对象不可达的对象们则被视作垃圾
哪些对象可以被视作GCRoot呢?
虚拟机栈中本地变量引用的对象
方法区中静态变量引用的对象
方法区中常量引用的对象
本地方法栈中的JNI引用的对象
垃圾回收算法有哪些呢?
1.标记-清除法:先遍历内存,标记垃圾对象,然后执行垃圾回收
缺点:遍历两次内存(效率较低) 容易产生大量内存碎片
2.复制算法:将内存分为两块,当其中一块内存满了,触发GC,将该区域的存活对象复制到另一个区域,然后将剩余对象清除,以此往复
优点:解决了内存碎片问题,效率更高
缺点:内存利用率较低
3.标记-整理算法:在标记-清除算法基础之上添加了整理的步骤
4.分代收集算法:
将内存区域分为新生代和老年代:对于经历了一定次数还没有死的对象我们把这类对象看做是老年对象,放到老年代,对于比较大的对象也是直接存放在老年代
MinorGC:发生在新生代的垃圾回收,GC速度较快(复制算法)
FullGC(整个堆得GC):MajorGC(老年代GC),GC速度较慢(标记-整理/标记-清除算法)
垃圾收集器:
Serial收集器(新生代):回收算法:复制算法,单线程GC,GC期间stw
ParNew收集器(新生代):回收算法:复制算法,多线程GC,期间stw
ParNew可以理解为是Serial的多线程版本
Parallel Scavenge收集器(新生代):
回收算法:复制算法,多线程GC,期间stw
Parallel Scavenge和ParaNew类似,但是前者可以自适应设置GC吞吐量,也可以自适应GC,无需手动设置哦Eden s0 s1区域大小
Serial Old(老年代):算法:标记-整理,单线程GC,gc期间stw
Parallel Old:回收算法:标记整理,多线程GC,GC期间stw(关注吞吐量的场景)
CMS收集器(老年代):全称:Concurrent Mark Sweep
它分为以下几个阶段:
a.初始标记:stw,将年轻带指向老年代的对象以及gc root直接关联的对象进行标记,速度很快
b.并发标记:不停止线程,遍历gc root下的其他关联对象,进行标记
c.并发预处理:由于并发标记阶段可能有的线程没有停止,所以它的gc root的引用很可能发生了改变,因此,将这些没有stop的线程的的标记进行重新标记
d.并发清除:基于标记结果,将之前的标记的垃圾进行并发清除,不stw
e.并发重置:清除本次cms GC的上下文信息,为下一次gc做准备
G1收集器:
G1垃圾收集器将内存分为若干个region,region主要分为以下四种类型:
Eden:eden 和suvivor均可视为年轻代的内存区域
Suvivor:
Old:老年代内存区域
Humongous:大对象的内存区域,收集器会将该区域视作老年代
G1垃圾回收器的GC机制:
a.young GC
Eden满了的时候,触发young gc,将eden的存活对象放到suvivor当中,原先的suvivor的对象转移至新的suvivor当中,或者年纪到了晋升为老年代存到old region当中
刚刚被gc的eden region会被放到空闲列表中,等待下次被使用
Mixed GC:
Mixed GC 会回收所有 Young Region,同时回收部分 Old Region
Mixed GC的垃圾回收算法和CMS类似,如图:
FullGC:复制对象的内存不够,或者无法分配足够的内存(比如,巨型对象没有足够的连续分区分配)时,会触发Full GC,Full GC 模式下,使用 Serial Old 模式,(标记整理算法)
Jdk9之后cms废弃,jvm1.8的默认垃圾收集器是Parallel Scavenge(新生代) + Parallel Old(老年代)
G1(Grabage-First)是一款面向服务端应用的垃圾收集器,主要针对配备多核cpu及大容量内存的机器,以及高概率满足GC停顿时间的同时,还兼顾高吞吐量的的性能特征