JVM常见知识点

JVM

JVM主要组成部分及其作用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1、类加载器(Class Loader):加载类文件到内存。Class Loader只管加载,只要符合文件结构就加载,至于能否运行,他不负责。那是有Exectution Engine 负责的。

2、执行引擎(Execution Engine):也叫解释器,负责解释命令,交由操作系统执行。

3、本地库接口(Native Interface):本地接口的作用是融合不同的语言为java所用

4、运行时数据区(Runtime Data Area):

img

1)。堆是java对象的存储区域,任何用new字段分配的java对象实例和数组,都被分配在堆上,java堆可用-Xms和-Xmx进行内存控制,jdk1.7以后,运行时常量池从方法区移到了堆上。

img

​ 新生代:老年代 = 1:2 Eden:s1: s2=8:1:1
在这里插入图片描述
在这里插入图片描述

2)方法区:用于存储已被虚拟机加载的(Class)类信息,(final )常量,(static )静态变量,常量池,即时编译器编译后的代码等数据。

3)**虚拟机栈:**虚拟机栈中执行每个方法的时候,都会创建一个栈桢用于存储局部变量表,操作数栈,动态链接,方法出口等信息。

栈:8大基本类型+对象引用+实例方法
栈运行原理:栈帧

4)**本地方法栈:**与虚拟机发挥的作用相似,相比于虚拟机栈为Java方法服务,本地方法栈为虚拟机使用的Native方法服务,执行每个本地方法的时候,都会创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等信息。

5)**程序计数器。**指示Java虚拟机下一条需要执行的字节码指令。

队列和栈是什么,列出它们的区别

1.队列(Queue):是限定只能在表的一端进行插入和在另一端进行删除操作的线性表

2.栈(Stack):是限定只能在表的一端进行插入和删除操作的线性表

3.队列先进先出(FIFO),栈先进后出(FILO)

双亲委派模型

双亲委派模式要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器,请注意双亲委派模式中的父子关系并非通常所说的类继承关系,而是采用组合关系来复用父类加载器的相关代码,类加载器间的关系如下:

img

双亲委派模式是在Java 1.2后引入的,其工作原理的是,如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是*双亲委派模式*。

如何判定对象是否可以被回收

1.引用计数算法(已被淘汰的算法)
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。

目前主流的java虚拟机都摒弃掉了这种算法,最主要的原因是它很难解决对象
之间相互循环引用的问题。尽管该算法执行效率很高。

2.可达性分析算法
目前主流的编程语言(java,C#等)的主流实现中,都是称通过可达性分析(Reachability Analysis)来判定对象是否存活的。这个算法的基本思路就是通过一系列的称为**“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连(用图论的话来说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的**。如下图所示,对象object 5、object 6、object 7虽然互相有关联,但是它们到GC Roots是不可达的,所以它们将会被判定为是可回收的对象。

è¿éåå¾çæè¿°

JVM有哪些垃圾回收算法

1.Mark-Sweep标记-清除)算法
这是最基础的垃圾回收算法,之所以说它是最基础的是因为它最容易实现,思想也是最简单的。标记-清除算法分为两个阶段:标记阶段和清除阶段。标记阶段的任务是标记出所有需要被回收的对象,清除阶段就是回收被标记的对象所占用的空间。
2.Copying(复制)算法
  为了解决Mark-Sweep算法的缺陷,Copying算法就被提了出来。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用的内存空间一次清理掉,这样一来就不容易出现内存碎片的问题。
3.Mark-Compact标记-整理)算法(压缩法
为了解决Copying算法的缺陷,充分利用内存空间,提出了Mark-Compact算法。该算法标记阶段和Mark-Sweep一样,但是在完成标记之后,它不是直接清理可回收对象,而是将存活对象都向一端移动,然后清理掉端边界以外的内存。
4.Generational Collection分代收集)算法
分代收集算法是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根据对象存活的生命周期将内存划分为若干个不同的区域。一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。

垃圾回收器都有哪些

本文要讨论的是 Oracle 的 HotSpot 虚拟机所使用的垃圾回收器。

常用垃圾回收器,如下图所示:

640?wx_fmt=png

新生代回收器:Serial、ParNew、Parallel Scavenge

老年代回收器:Serial Old、Parallel Old、CMS

整堆回收器:G1

其中相互连线的垃圾回收器,表示可以相互搭配使用

目前常用的商用垃圾收集器都使用的是分代垃圾回收方式。

分代垃圾回收器把内存分为:新生代(Young Generation)和老生代(Tenured Generation),如下图所示:

640?wx_fmt=png

默认情况下,新生代和老生代的内存比例是 1:2,该值可以通过 -XX:NewRatio 来设定。

新生代(Young Generation)

程序中的大部分对象都符合“朝生夕死”的特性,所以绝大数新创建的对象都会存放在新生代,除非是大对象会直接进入老生代。新生代采用的是复制算法,这样可以更高效的回收内存空间。

新生代有细分为:Eden、Form Survivor、To Survivor 三个区域,默认的比例是 8:1:1,可以通过 -XX:SurvivorRatio 来设定。

新生代垃圾回收的执行过程:

1、Eden 区 + From Survivor 区存活着的对象复制到 To Survivor 区;

2、清空 Eden 和 From Survivor 分区;

3、From Survivor 和 To Survivor 分区交换(From 变 To,To 变 From)。

老生代(Tenured Generation)

老生代垃圾回收的频率比新生代低,存放的主要对象是:

1、新生代对象经过 N 次 GC 晋升到老年代。

可以通过设置 -XX:MaxTenuringThreshold=5 来设置,默认值是 15 次。

2、大对象直接存储到老生代。

所谓的“大对象”指的是需要连续存储空间的对象,比如:数组。

当大对象在新生代存储不下的时候,就需要分配担保机制,把当前新生代的所有对象复制到老年代中,因为分配担保机制需要涉及大量的复制,会导致性能问题,所有最好的方案是直接把大对象存储到老生代中。

通过参数 -xx:PretrnureSizeThreshold 来设定大对象的值。

注意:该参数只有 Serial 和 ParNew 垃圾回收器有效。

G1

G1 GC 这是一种兼顾吞吐量和停顿时间的 GC 实现,是 JDK 9 以后的默认 GC 选项。G1 可以直观的设定停顿时间的目标,相比于 CMS GC,G1 未必能做到 CMS 在最好情况下的延时停顿,但是最差情况要好很多。

G1 GC 仍然存在着年代的概念,但是其内存结构并不是简单的条带式划分,而是类似棋盘的一个个 region。Region 之间是复制算法,但整体上实际可看作是标记 - 整理(Mark-Compact)算法,可以有效地避免内存碎片,尤其是当 Java 堆非常大的时候,G1 的优势更加明显。

640?wx_fmt=png

G1 吞吐量和停顿表现都非常不错,并且仍然在不断地完善,与此同时 CMS 已经在 JDK 9 中被标记为废弃(deprecated),所以 G1 GC 值得深入掌握。

G1 运行过程:

1、初始标记

标记 GC Roots 直接关联的对象,需要 Stop The World 。

2、并发标记

从 GC Roots 开始对堆进行可达性分析,找出活对象。

3、重新标记

重新标记阶段为了修正并发期间由于用户进行运作导致的标记变动的那一部分对象的标记记录。这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短,也需要 Stop The World 。

4、筛选回收

首先对各个 Region 的回收价值和成本进行排序,根据用户所期望的 GC 停顿时间来制定回收计划。这个阶段可以与用户程序一起并发执行,但是因为只回收一部分 Region,时间是用户可控制的。

线程类型: 多线程

使用算法: 复制、标记-整理

指定收集器: -XX:+UseG1GC(JDK 7u4 版本后可用)

Serial

Serial 最早的垃圾回收器,JDK 1.3.1 之前新生代唯一的垃圾回收器,使用的是单线程串行回收方式,在单 CPU 环境下性能较好,因为单线程执行不存在线程切换。

线程类型: 单线程

使用算法: 复制算法

指定收集器: -XX:+UseSerialGC

Serial Old

Serial 收集器的老年代版本,同样也是单线程的。它有一个实用的用途作为CMS收集器的备选预案,后面介绍CMS的时候会详细介绍。

线程类型: 单线程

使用算法: 标记-整理

指定收集器: -XX:+UseSerialGC

ParNew

ParNew 其实就是 Serial 的多线程版本,可以和 Serial 共用很多控制参数,比如:-XX:SurvivorRatio , ParNew 可以和 CMS 配合使用。

线程类型: 多线程

使用算法: 复制

指定收集器: -XX:+UseParNewGC

640?wx_fmt=png

注:图片来源于零壹技术栈)

Parallel Scavenge

Parallel 和 ParNew 收集器类似,也是多线程的,但 Parallel 是吞吐量优先的收集器,GC停顿时间的缩短是以吞吐量为代价的,比如收集 100MB 的内存,需要 10S 的时间,CMS 则会缩短为 7S 收集 50 MB 的内存,这样停顿的时间确实缩少了,但收集的频率变大了,吞吐量就变小了。

线程类型: 多线程

使用算法: 复制

指定收集器: -XX:+UseParallelGC

Parallel Old

Parallel Old 是 Parallel 的老生代版本,同样是吞吐量优先的收集器。

线程类型: 多线程

使用算法: 标记-整理

指定收集器: -XX:+UseParallelOldGC

CMS

CMS(Concurrent Mark Sweep)一种以获得最短停顿时间为目标的收集器,非常适用B/S系统。

使用 Serial Old 整理内存。

CMS 运行过程:

640?wx_fmt=png

(注:图片来源于零壹技术栈)

1、初始标记

标记 GC Roots 直接关联的对象,需要 Stop The World 。

2、并发标记

从 GC Roots 开始对堆进行可达性分析,找出活对象。

3、重新标记

重新标记阶段为了修正并发期间由于用户进行运作导致的标记变动的那一部分对象的标记记录。这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短,也需要 Stop The World

4、并发清除

除垃圾对象。

CMS 缺点:

1、对 CPU 资源要求敏感。

CMS 回收器过分依赖于多线程环境,默认情况下,开启的线程数为(CPU 的数量 + 3)/ 4,当 CPU 数量少于 4 个时,CMS 对用户本身的操作的影响将会很大,因为要分出一半的运算能力去执行回收器线程。

2、CMS无法清除浮动垃圾。

浮动垃圾指的是CMS清除垃圾的时候,还有用户线程产生新的垃圾,这部分未被标记的垃圾叫做“浮动垃圾”,只能在下次 GC 的时候进行清除。

3、CMS 垃圾回收会产生大量空间碎片。

CMS 使用的是标记-清除算法,所有在垃圾回收的时候回产生大量的空间碎片。

注意:CMS 收集器中,当老生代中的内存使用超过一定的比例时,系统将会进行垃圾回收;当剩余内存不能满足程序运行要求时,系统将会出现 Concurrent Mode Failure,临时采用 Serial Old 算法进行清除,此时的性能将会降低。

线程类型: 多线程

使用算法: 标记-清除

指定收集器: -XX:+UseConcMarkSweepGC

JVM调优工具

Jconsole : jdk自带,功能简单,但是可以在系统有一定负荷的情况下使用。对垃圾回收算法有很详细的跟踪。

JProfiler:商业软件,需要付费。功能强大。

VisualVM:JDK自带,功能强大,与JProfiler类似。推荐。

常用的 JVM 调优的参数

-Xms2g:初始化堆大小为 2g;
-Xmx2g:堆最大内存为 2g;
-XX:NewRatio=4:设置年轻的和老年代的内存比例为 1:4;
-XX:SurvivorRatio=8:设置新生代 Eden 和 Survivor 比例为 8:2;
–XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器组合;
-XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器组合;
-XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器组合;
-XX:+PrintGC:开启打印 gc 信息;
atio**=4:设置年轻的和老年代的内存比例为 1:4;
-XX:SurvivorRatio=8:设置新生代 Eden 和 Survivor 比例为 8:2;
–XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器组合;
-XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器组合;
-XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器组合;
-XX:+PrintGC:开启打印 gc 信息;
-XX:+PrintGCDetails:打印 gc 详细信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值