java虚拟机

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java虚拟机相关的知识,希望对你有一定的参考价值。

一.jmm内存模型
1.程序计数器:当前线程所执行的字节码的行号指示器。通过改变计数器的值来确定下一条要执行的字节码指令。
2.java虚拟机栈:java方法执行的内存模型,每个java方法执行时会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
3.本地方法栈
4.java堆:存放对象实例;堆可以细分为新生代(Eden区和survivor1、survivor2)和老年代
5.方法区:存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等信息。永久代
6.运行常量池:方法区的一部分。
7.直接内存
二.异常判定

三.算法
1.对象存活判定算法、
1.1引用计数:给对象添加一个引用计数器,每当一个地方引用它,计数器加1;引用失效时,计数器减1
1.2可达性分析算法:通过一系列的GC ROOTS作为对象起始点,从这些节点开始向下搜索,搜索走过的路径称为引用链,当一个对象到GC ROOTS没有任何引用链相连时,证明对象不可用。
1.3四种引用:强引用,类似Object obj = new Object(),只要强引用存在,对象永远不会被回收;软引用,有用但非必要的对象,内存溢出异常前,会尝试回收此类对象;弱引用,垃圾回收时,不管当前内存是否足够,都会回收此类对象;虚引用,无法对虚引用获取对象实例。
1.4对象需要两次标记才能被回收,对象进行可达性分析后,没有与GC ROOTS的引用链,则第一次被标记,并进行一次筛选,有finalize()方法的进行自救。
2.垃圾收集算法
2.1标记-清除
第一个阶段标记需要回收的对象,第二个阶段回收标记的对象。
缺点:1>标记和清除效率低,2>标记后会产生大量不连续的内存碎片。
2.2复制
将内存分为大小相同的两块,每次只是用其中的一块,当这块内存用完后,将存活的对象复制到另一块内存,然后清理掉本块内存使用的对象。
优点:高效、不用考虑内存碎片
缺点:内存缩小为原来一半,代价太高,不适合对象存活率高(例如老年代)
目前商业虚拟机都采用此算法,针对朝生夕死的对象比较合适。将新生代分为8:1:1(Eden:Survivor1:Survivor2);使用过程中只使用Eden区和其中一个Survivor区,回收的时候,该Eden和Survivor中存活对象复制到另外一个Survivor区,然后清空该Eden和Survivor区
2.3标记-整理
第一个阶段标记对象,第二个阶段将标记的对象进行整理,存活对象向一端移动,然后清理掉端边界以外的对象。
2. 4分代收集算法
将java堆分为新生代和老年代,各个年代采用适当的算法。(新生代采用赋值算法,老年代采用标记-清理或者标记-整理算法)
2.5.HotSpot的算法实现
2.5.1.枚举根节点
2.5.2.安全点:当线程执行到安全点之后才能进行gc停顿。
如何在gc发生时让线程跑到安全点:
2.5.2.1.抢断式中断(弃用):直接中断所有线程,不在安全点的,恢复线程,跑到安全点。
2.5.2.2.主动式中断:设置一个标志,各个线程轮询这个标志,为真时自动中断挂起。
2.5.3.安全区域
对于处理sleep和blocked状态的线程:使用安全区域来解决,线程执行到safe region中的代码时,标志自己进入safe region,当这段时间
jvm发起gc时,标志为safe region的线程不处理;当线程要离开safe region区域时,要判断系统是否完成了枚举根节点,完成了才能继
续执行,否则等待。
四.垃圾收集器
1.Serial收集器,Serial Old
Serial/Serial Old:单线程收集器,stop the world:运行的时候会暂停所有的用户线程,只进行垃圾回收
Serial :复制算法
Serial Old : 标记整理算法

优点:简单高效
缺点:stop the world
适用场景:运行在Client模式下的新生代,新生代占用内存空间小。
2.ParNew收集器
新生代收集器;Serial收集器的多线程版本,Server模式下的虚拟机首选新生代收集器,适用于多核cpu。Serial和ParNew可以配置CMS收集器适用。
3.Parallel Scavenge,Parallel Old
并行多线程收集器,收集器的关注点不同,Parallel Scavenge收集器的目标是达到一个可控制的吞吐量。cpu运行用户代码的时间/cpu总消耗时间。
Parallel Scavenge:复制算法
Parallel Old:标记整理算法
在注重吞吐量和CPU资源敏感的场合使用。

4.CMS收集器
面向服务端
以获取最短回收停顿时间为目标的收集器。
基于标记清除算法实现,用于老年代
整个过程分为四个步骤:
4.1初始标记:标记GC ROOTS能关联到的对象,stop the world, 时间很短
4.2并发标记:GC ROOTS TRACING的过程,与用户线程并发执行。
4.3重新标记:修正并发标记期间因用户程序继续运作而导致标记产生表动的对象标记记录。stop the world,时间短
4.4并发清除:清除垃圾对象,与用户线程并发执行。
优点:并发收集、低停顿
缺点:1.对cpu资源非常敏感
2.无法处理浮动垃圾,处理Concurrent Model Failure失败:并发清理阶段产生的垃圾称为浮动垃圾。
3.产生内存空间碎片:+UseCMSCompactAtFullCollection,默认开启,进行Full GC时开启碎片整理。-XX:CMSFullGCBforeCompaction,执行多少次不压缩的Full GC后,接着执行一次带压缩的Full GC默认为0,每一次都是Full GC。
5.G1收集器
面向服务端
收集过程:
1.初始标记:标记GC ROOTS能关联到的对象,并且修改TAMS(Next Top At Mark Start)的值,保证用户在并发执行时能够在正确的可用的
region中创建新对象,stop the world, 时间很短
2.并发标记:对堆中对象进行可达性分析,找出存货对象,用时时间长可并发执行。
3.最终标记:修正在并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录。stop the world,时间短
4.筛选回收:首先对各个region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划。
优点:1.并发与并行:G1能充分利用多CPU、多核环境下硬件优势
2.分代收集:不需要其他收集器配置就能独立管理好整个GC堆,能采用不同的方式来管理新创建的对象和熬过多次GC的旧对象。
3.空间整合:整体来看基于标记-整理算法。局部来看(两个region之间)是基于复制算法。
4.可预测的停顿,让使用者明确指定在一个长度M毫秒的时间内垃圾收集的时间不得超过N毫秒
G1收集器的原理:将内存分为多个大小相等的独立区域(region)(使得新生代和老年代不再物理隔离),G1跟踪各个regionn里面的垃圾堆积的价值大
小(所获得的空间大小以及回收所需要时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的region,保证G1收
集器在有限的时间内可以获取尽可能高的收集效率。

6.垃圾收集器参数

参数  描述
UseSerialGC 虚拟机运行在client模式下的默认值,打开此开关后,适用Serial+Serial Old的收集器组合进行内存回收
UseParNewGC 打开此开关后,适用ParNew+Serial Old的收集器进行内存回收
UseConcMarkSweepGC 打开此开关后,适用ParNew+CMS+Serial Old的收集器组合进行内存回收,Serial Old收集器将作为CMS收集器出现Concurrent Mode Failure失败后的后备收集器使用
UseParallelGC 虚拟机运行在Server模式下的默认值,打开此开关后,使用Parallel Scavenge+Serial Old的收集器进行内存回收
UseParallelOldGC 打开此开关后,使用arallel Scavenge+Parallel Old的收集器组合进行内存回收
SurvivorRatio 新生代中Een区域与Survivor区域的容量比值,默认为8,代表Eden:Survivor=8:1
PretenureSizeThreshold 直接晋升到老年代的对象大小,设置这个参数后,大于这个参数的对象将直接在老年代分配
MaxTenuringThreshold  进行到老年代的对象年龄。每个对象在坚持过一次minor GC后年龄加1,当超过这个参数值的时候进入老年代
UseAdaptiveSizePolicy 动态调整java堆中各个区域的大小以及进入老年代的年龄
HandlePromotionFailure 是否允许分配担保失败,即老年代的剩余空间不足以应付新生代的整个Eden和Survivor区的所有对象都存活的极端情况
ParallelGCThreads 设置并行GC时进行内存回收的线程数
GCTimeRatio GC时间占总时间的比率,默认值为99,即允许1%的GC时间,仅在使用Parallel Scavenge收集器时生效
MaxGCPauseMillis 设置GC的最大停顿时间。仅在使用Parallel Scavenge收集器时生效
CMSInitatingOccupancyFraction 设置CMS收集器在老年代空间被使用多少后触发垃圾收集。默认值为68%,仅在使用CMS收集器时生效
UseCMSCompactAtFullCollection 设置CMS收集器在完成垃圾收集后是否要进行一次内存碎片整理。仅在使用CMS收集器时生效
CMSFullGCsBeforeCompation 设置CMS收集器在进行若干次垃圾收集后再启动一次内存碎片整理。仅在使用CMS收集器时生效


7.内存分配和回收策略
1.对象优先在eden分配
2.大对象直接进入老年代
3.长期存活的对象直接进入老年代
4.survivor空间中相同年龄的对象大小的总和大于survivor空间的一半,年龄大于或等于该年龄的对象可以直接进去老年代

























































































以上是关于java虚拟机的主要内容,如果未能解决你的问题,请参考以下文章

java虚拟机和java内存区域概述

java虚拟机学习-触摸java常量池(13)

深入理解Java虚拟机:JVM高级特性与最佳实践的内容简介

android -------- java虚拟机和Dalvik虚拟机

Java虚拟机体系结构

JAVA虚拟机体系结构