2

什么是jvm

jvm是java虚拟机的缩写。所有的java程序都是在jvm上运行的。做好jvm的优化能大大提升系统的性能

jvm体系结构概览

clipboard.png

大致流程如图:编译好的class文件通过类加载器从物理结构转换成运行时数据区结构。再通过jvm内置执行引擎和本地方法的调用实现 ps:本地方法就是带有native关键字的方法

其中方法区和堆是最重要的两块区域(这里是以java7为参照。java8没有方法区)
因为这两块是gc算法作用的最主要区域

gc算法

如果需要收集垃圾,则必须先找到垃圾。

1.引用计数法

clipboard.png

解释:每个对象都带有一个引用计数器,当其他声明的变量指向这个对象时候,计数器就+1,当指向消逝时候,就将计数器-1.垃圾回收只回收计数为0的对象。
缺点:无法回收循环引用的情况,比如A引用了B,B引用了C,C引用了A. 这种GC算法还需要编译器进行配合,对对象引用进行计数,需要额外生成代码。

2.可达性分析

clipboard.png

解释:设立若干个根对象,当一个对象不能通过任何根对象引用达到,那么这个对象在finalize中有一次可以请求“重生”机会,或者直接忽略finalize,选择直接死亡。

找到垃圾后,开始垃圾收集

标记清除算法

clipboard.png

clipboard.png

简单解释下:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。它的主要缺点有两个:一个是效率问题,标记和清除过程的效率都不高;另外一个是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致,当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作

这是最基本的gc算法,后续的gc算法都是根据这种思路来改进的

标记压缩算法

clipboard.png

clipboard.png

标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存

复制算法

clipboard.png

clipboard.png

将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

分代收集算法

clipboard.png

把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或“标记-整理”算法来进行回收。
这里总共会有三种gc

clipboard.png
不同的gc使用不同的gc算法

clipboard.png

clipboard.png

注:默认新生代eden区和survivor区比例为8:1:1

火车算法

最先进的g1收集器使用的gc算法,相对于分代收集,它的分区处理更彻底

clipboard.png

在火车算法中,内存被分为块,多个块组成一个集合。为了形象化,一节车厢代表一个块,一列火车代表一个集合,火车与车箱都按创建顺序标号,每个车厢大小相等,但每个火车包含的车厢数不一定相等;每节车箱有一个被记忆集合,而每辆火车的记忆集合是它所有车厢记忆集合的总和;算法在执行时,要么收集最小数字车厢,要么收集最小数字火车。如果整节火车都是垃圾,就收集最小数字火车。

现有该场景

clipboard.png

内存分为四块。 其中F,C,D,E是垃圾。G,A,B存活对象
首先扫描第一块内存。发现G是存活对象,F是垃圾。利用记忆集合将G的应用存到最后一块内存
回收第一块内存

clipboard.png

如果再次发生gc,则同样扫描第二块内存。发现A,B都是存活对象,都移到最后一块内存。回收第二块内存

clipboard.png

因为火车算法是将一块内存的对象移到另一块内存上并清除原来的内存。很像复制算法。
所以火车算法就被称为局部复制,外部标记清理

火车算法的问题

  1. 如果要保存一个比内存块大的对象怎么办
  2. 如果两个对象在不同内存块相互调用怎么办

垃圾回收器

垃圾收集器一览

clipboard.png

术语

clipboard.png

clipboard.png

新生代垃圾收集器

clipboard.png

serial (串行收集器)

特点

串行,stop the world

适用场景

单cpu,新生代内存小,对暂停时间要求不高的应用
是client和32位windows的默认垃圾收集器

对象分配到old区的情况

  1. 对象大于eden区
  2. 大对象直接分到old区

晋升规则

  1. 经历多次gc后仍存活的对象
  2. to survivor区装不下直接晋升

parallel scanvenge收集器

特点

并行,stop the world
并行线程数默认值:cpu <= 8 则 线程数=cpu数 cpu>8 则(3+cpu*5)/8
可自定义线程数 :
clipboard.png

适用场景

多cpu,对暂停时间较短的应用
是server和2核cpu,2g内存的默认选择

对象分配到old区的情况

  1. 在eden区分配失败,且对象大于eden的一半
  2. 大对象直接分到old区

晋升规则

  1. 经历多次gc后仍存活的对象
  2. to survivor区装不下直接晋升

parnew

特点

并行,stop the world
serial的多线程版
可搭配cms
不能搭配parllel old

适用场景

多cpu,对暂停时间较短的应用
是server和2核cpu,2g内存的默认选择

对象分配到old区的情况

  1. 对象大于eden区
  2. 大对象直接分到old区

晋升规则

  1. 经历多次gc后仍存活的对象
  2. to survivor区装不下直接晋升

老年代垃圾收集器

clipboard.png

serial old

特点

串行,stop the world ,标记整理算法,清除时间长

适用场景

是client和32位windows的默认垃圾收集器

parallel old

特点

串行,stop the world ,标记整理算法

适用场景

是server和2核cpu,2g内存的默认选择

cms

特点

并行,并发,标记清理算法
默认并发线程数:(新生代并行线程数+3)/4

适用场景

暂停时间短,很适用于追求高响应速度的互联网引用

执行步骤

clipboard.png

缺点

  1. 和应用抢占cpu
  2. gc耗时长
  3. 浮动垃圾
  4. 内存碎片

第一篇先到这儿了。先消化一下。后面再写一篇关于调优的


木木甫
494 声望23 粉丝

已工作的应届生。希望能和大家多多交流技术问题,