JVM结构
2020-02-11 11:07:28 0 举报
JVM结构
作者其他创作
大纲/内容
ParNew
本地方法栈
JVM内存模型解析:
并发重置
G1垃圾收集分类YoungGC:新对象进入Eden区存活对象拷贝到Survivor区存活时间达到年龄阈值时,对象晋升到Old区MixedGC:不是FullGC,回收所有的Young和部分Old(根据期望的GC停顿时间确定old区垃圾收集的优先顺序)
Old Generation(1/3堆空间)
新生代采用复制算法老年代采用标记-整理算法
ParNew收集器
应用程序线程
筛选回收:该阶段首先对各个Region的回收价值和成本进行排序,根据用户期望的GC停顿时间来制定一个回收计划,这个阶段其实也可以做到与用户程序一起并发执行,但是因为只回收一部分Region,时间是用户控制的,而且停顿用户线程将大幅度提高收集效率
java堆内存模型解析:
方法区(线程共享):类的所有字段和方法字节码,以及一些特殊方法如构造方法,接口代码也再此定义。也就是静态变量+常量+类信息(构造方法/接口定义)+运行时常量池都存在该方法区中。也就是类的模板
JVM由以下三个主要的子系统构造(运行时数据区,类装载子系统,执行引擎)
标记-清除算法:首先标记出需要回收的算法,在标记完成后统一回收所有标记的对象。它是最基础的收集算法,但是会出现两个明显的问题:效率问题,空间问题(标记清除后会产生大量连续的碎片)复制算法:为了解决效率问题及空间问题,“复制\"收集算法就出现了。它可以将内存分为大小相同的两块,每一次使用其中的一块。当这一块内存使用完了后,就会将还存活的对象复制到另一块,然后把之前的空间一次清理掉。标记-整理算法:根据老年代的特点特出的一种标记算法,标记过程仍然与\"标记-清除\"算法一样,只不过步骤不是直接回收可回收对象,而是让所有存活的对象向一段移动,然后直接清理掉段边界以外的内存。分代收集算法:当前虚拟机的垃圾收集算法都采用分代收集算法,这种算法只是一种思想,只是根据对象存活的周期的不同将分为几块。一般将java堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾算法。
Serial
主要是old区使用采用标记-清除算法
向上委派
如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。
Eden(8/10)
程序计数器(线程私有):就是一个指针,指向方法区中的方法字节码(用来存储指向下一条指令的地址)由执行引擎读取下一条指令。
Parallel old收集器
重新标记
局部变量表:用于存放方法参数和局部变量
标记-清除算法
筛选回收
父类加载失败交由子加载器自行处理
复制算法
Serial Old
每个线程都有一个独立的(java栈,本地方法栈,程序计数器)(堆,方法区)是共享的
main()方法栈帧
操作数栈:是一个先进后出的栈,方法执行过程中,会有各种字节码指令往操作数栈中存取数据,最后导入局部变量表中。
动态链接
系统类加载器Application ClossLoader
元空间:直接内存也就是元数据区,它是方法区的一个实现,让垃圾回收可以不用再为方法区去写一个内存管理了,jdk1.8之前叫永久代,内存再堆中会出现OOM异常,jdk1.8开始变为元数据区,内存改变为直接内存,不会出现OMM异常。
E
Parallel Old
类加载器机制:全盘负责委托机制:当一个ClassLoader加载一个类时,除非显示的使用另一个ClassLoader,该类所依赖和引用的类也由这个ClassLoader载入。双亲委派机制:指先委派父类加载器寻找目标类,在找不到的情况下在自己的路径中查找载入目标类。
GC线程应用线程暂停
分代收集算法
serial收集器
堆(线程共享):虚拟机启动时创建,用于存放对象实例,几乎所有对象(包括常量池)都在堆上分配内存,当对象无法再申请到内存时将抛出OutOfMemoryError异常。同时也是垃圾收集器管理的主要区域。可通过-Xmx -Xms参数来分别指定最大堆和最小堆
类加载过程:加载-连接(验证,准备,解析)-初始化-使用-卸载 类加载:类加载器将class文件加载到虚拟机的内存 加载:再硬盘上查找并通过IO读入字节码文件 连接:执行校验,准备解析(可选)步骤 校验:校验字节码文件的正确性 准备:给类的静态变量分配内存,并赋予默认值 解析:类装载器装入类所引用的其他所有类 产生化:对类的静态变量初始化为指定的值,执行静态代码块
并发清理
可达性分析算法这个算法就是通过一系列的\"GC Roots\"的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链接时,说明该对象是可回收的。GC Roots根节点:类加载器,Thread,虚拟机栈的本地变量表,static成员,常量引用,本地方法栈的变量等等 。
类装载子系统
Java栈内存模型
方法出口
优先调整堆的大小让服务器自己来选择如果内存小于100M,使用串行收集器如果是单核,并且没有停顿时间的要求,串行或JVM自己选择如果允许停顿时间超过1秒,选择并行或者JVM自己选如果响应时间最重要,并且不能超过1秒,使用并发收集器下图有连线的可以搭配使用,官方推荐使用G1,因为性能高
Serial Old收集器Serial收集器的老年代版本,它同样是一个单线程收集器。主要用途:1.JDK1.5及以前版本中与Parallel Scavenge收集器搭配使用。另一种是CMS收集器的后备方案。
java栈内存模型解析:
CMS收集器
Serial Old收集器
MetaSpace
初始标记
判断对象算法可回收?
自定义类加载器Custom ClossLoader
最终标记
动态链接:将多态的形式转换为直接引用
类加载器种类:启动类加载器:负责加载JRE的核心类库,如jre目标下的rt.jar.charsets.jar等。扩展类加载器:负责加载JRE扩展目录ext中的JAR类包。系统类加载器:负责加载ClassPath路径下的类包。用户自定义加载器:负责加载用户自定义路径下的类包 。
并发重置 :这个阶段,重置CMS收集器的数据结构,等待下一次垃圾回收。
Young Generation(1/3堆空间)年轻代
重新标记:重新标记阶段是为了修正并发标记期间因用户程序继续运行而导致标记产生变化的那一部分对象的标记记录,这个阶段比初始化阶段长,但远远比并发标记阶段短。
CMS备选
ParallelScavenge
双亲委派机制
GC线程多线程并发应用线程暂停
双亲委派模式优势沙箱安全机制:自己写的String.class类不会被加载,这样便可以防止核心API库被随意篡改。避免类的重复加载:当父类已经加载了该类时,就没有必要再加载一次了
主要优点:并发收集、低停顿。但是它有下面三个明显的缺点:1.对CPU资源敏感(会和服务抢资源);2.无法处理浮动垃圾(在java业务程序线程与垃圾收集线程并发执行过程中又产生的垃圾,这种浮动垃圾只能等到下一次gc再清理了);3.它使用的回收算法-“标记-清除”算法会导致收集结束时会有大量空间碎片产生。
年轻代
标记-整理算法
局部变量表
引用计数法给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加1;当引用失效,计数器就减1;任何时候计数器为0的对象就是不可能再被使用的。这个方法既简单而且效率高,但是这种算法很难对象之间相互循环引用的问题。所以目前主流的虚拟机中并没有选择这个算法来管理内存。
G1收集器在后台维护了一个优先列表,每次根据允许的收集时间,优先选择回收价值最大的Region(这也是它的名字Garbage-First的由来)。这种使用Region划分内存空间以及有优先级的区域回收方式,保证了G1收集器在有限时间内可以尽可能高的收集率
S
垃圾回收算法
并发清除:开启用户线程,同时GC线程开始堆未标记的区域做清扫收。
初始标记:在此阶段G1 GC对根进行标记。该阶段与常规的(STW)年轻代垃圾回收密切相关
方法区
初始标记:暂停所有的其他线程(STW),并记录下直接与root相连的对象,速度很快。
serial收集器单线程收集器,收集时只会有一条垃圾收集线程去完成工作,并且它在进行垃圾收集时会暂停其他所有的工作线程,直到垃圾收集结束为止。serial收集器优点在于它简单而高效(与其他收集器的单线程相比),并没有线程交互的开销,自然可以获得很高的单线程收集效率。
类加载子系统解析:
Parallel Scavenge收集器该收集器类似于ParNew搜集器,它的的点在于:Parallel Scavenge收集器关注点是吞吐量(高效率的利用CPU)。CMS等垃圾收集器的关注点更多的是用户的体验感。Parallel Scavenge收集器提供了很多参数供用户选择出最合适的停顿时间或最大吞吐量,如果堆收集器运作不太了解的话,可以交给虚拟机去完成。
CMS
CMS收集器(-XX:+UseConcMarkSweepGC)CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。它非常符合注重用户体验的应用上使用,它是HotSpot虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。它的运作过程相比于前面几种垃圾收集器来说更加复杂一些;整体过程分为五个步骤:
并发标记
操作数栈
堆
Parallel old收集器Parallel Scavenge收集器的老年代版本。使用多线程和标记-整理算法。在注重吞吐量以及CPU资源的场合,都可以优先考虑Parallel Scavenge收集器和Parallel Old收集器。
G1线程
ParNew收集器该收集器是Serial收集器的多线程版本,除了使用多线程进行垃圾收集外,其他和Serial收集器完全一样。它是许多运行在Server模式下的虚拟机的首要选择,除了Serial收集器外,只有它能与CMS收集器(并发收集器)配合工作
From(1/10)
java堆内存模型
执行引擎
拓展类加载器Extension ClossLoader
Parallel Scavenge收集器
启动类加载器Bootstrop ClossLoader
并发标记:G1 GC在整个堆中查找可访问的(存活的)对象
年轻代:类诞生,成长,消亡的区域,一个类在这里产生,应用,最后被垃圾收集器收集,结束生命。新生区分两个区域:伊甸园区(Eden space)和幸存者区(Survivor space),所有内都在伊甸园区被new出来。幸存区有两个:From区和To区。当伊甸园的空间用完时,程序有需要创建对象,JVM的font color=\"#ff66b3\
最终标记:该阶段是STW回收,帮助完成标记周期
其他方法栈帧(一个方法对应一个栈帧)
主要特点并发与并行:G1能充分利用CPU,多核环境下的硬件优势,使用多个CPU来缩短STW停顿时间。部分其他收集器需要停顿Java线程来执行GC动作,G1收集器任然可以通过并发的方式来让java程序继续执行。分代收集:虽然G1可以不需要其它收集器配合就可以独立完成整个GC堆,但还是保留了分代的概念。空间整理:与CMS的\"标记-清理\"算法不同,G1从整体来看是基于\"标记整理\"算法实现的垃圾收集;从局部上来看是基于\"复制\"算法实现的。可预测的停顿:G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定一个长度为M毫秒的时间片段内完成垃圾收集。
垃圾收集器
用户线程
老轻代
G1
运行时数据区(java内存模型)
CMS线程
To(1/10)
老年代:新生区经过多次GC任然存活的对象移入老年区。若老年区也满了,那么这个时候将产生MajorGC(FullGc)进行老年区的清理。若老年区执行Full GC后依然无法保存对象,则出现OOM异常(\"OutOfMemoryError\")
如何选择垃圾收集器
方法出口:当一个方法执行完后会退出,并指向调用该方法的指令后面的一个指令地址。
java栈
H
老年代
G1收集器(-XX:+UseConcMarkSweepGC)G1(Garbage-First)是一款面向服务器的垃圾收集器,主要针对配置多颗处理器及大容量内存的机器。以及高概率满足GC停顿时间要求的同时,还具备高吞吐量性能特征。使用G1收集器需要忘记原有的内存分配。span style=\"font-size: inherit;\
G1收集器
Java栈(线程私有):Java线程执行方法的内存模型,一个线程对应一个栈,每个方法在执行的同时都会创建一个栈帧,不存在垃圾回收问题,只要线程一结束该栈就释放,生命周期和线程一致。
程序计数器
本地方法栈(线程私有):标记未native的方法即为本地方法,一般为C语言所写,在Execution Engine执行时加载本地方法库
并发标记:同时开启GC和用户线程,用一个闭包结构区记录可达对象因为用户线程可能会不断更新引用域,所以无法保证可达性分析的实时性。所以这个算法会跟踪记录这些发生引用更新的地方。
O
0 条评论
下一页