个人对JVM五大部分的总结(欢迎网友指点、补充、指出错误)

因为我对Heap的文字描述比较多,先单独抽取出来:

--------

--------

new对象、数组等分配的内存空间。

heap又分为新生代Young和老年代Old(两者1:2大小)。新生代细拆为3部分(Eden、from、to,8:1:1),from和to合称为Survivor区。

新分配的对象先到新生代的Eden区,要是Eden放不下,就会触发Minor GC垃圾回收,新生代使用的GC算法为引用计数法,首先Eden中存活的对象(仍然有在程序运行中被引用,这个引用可能是Method方法区中的常量池存储的引用【String引用、或者非浮点数的引用池-128~127】,也可能不是)放到to区,要是to有放不下的部分(比如一个很大的对象,例如一个大数组之类的),就直接放到old老年代区域;接着from区,要是里面的对象引用计数达标(一般是15,或者你可以另外自己设置),就直接把这个对象放到Old老年代,其他存活对象放到to区,同样放不下的也是直接放old区,然后没有存活的(也就是引用计数为0,其他人不引用这个对象了)就舍弃;to区没有所谓的变动,这里提一下,“GC算法指的是把符合XXX条件的东西视为还活着的对象的算法”,前面提到的Minor GC指的是新生代进行一次垃圾回收的整个过程,新生代垃圾回收的方式是复制算法,就是上述的把存活的复制到to或者old区域,然后没存活的就回收其内存空间,这样内存内有碎片,即内存不是连续的,但是新生代垃圾回收比较频繁,使用这种复制算法来垃圾回收效率高,而且本省新生代占用heap的空间也就1/3,所以浪费的内存空间可以接收。

接着谈Old区,Old区就是老年代,里面的对象要么是Young中存活下来的经常被引用的小对象,要么就是引用次数不一定多、但是占用内存很大所以被直接分配过来的大对象。这里有个带有歧义的问题,我也无法下定论,就是Major GC和Full GC区别,有人说前者是老年代的GC,有人说前者是永久代的GC,Full GC则有说是老年代回收、也有说是新老年代回收,更有说是所有内存的回收。这里不多纠结,但是只要知道Major GC和Full GC往往都会涉及到老年代的GC。触发老年代GC的条件有很多,这里只简单列举,比如新生代的对象进入老年代过于频繁,其速度大于了老年代回收的速度,平均下来老年代将不够新生代的对象进入;或者简单粗暴老年代空间不够用了,那么肯定得进行Old区的GC流程。其他触发Old区回收的情况自行查询、脑补,基本都是围绕着老年代空间将要或者已经不够用展开的话题。Old区的GC算法是可达性算法{{可达性算法通过遍历GC ROOT根节点来判断对象是否被引用,避免了引用计数法出现的2个垃圾对象互相引用而不被回收的尴尬场景,可以理解为java程序里面把所有的引用用一张无向图表示,每个引用之间有一条边,这样就形成复杂的图,而互相引用的垃圾对象自成一个环路,和GC ROOT节点所在的大无相图没有联系,这样就可以把这中垃圾引用对象视为无用对象,被回收。什么对象能作为GC ROOT,一般指的是垃圾回收器对象【其有一套规则指定哪些对象可以作为GC ROOT,java中的GC ROOT对象通常包括:JVM Stack中栈帧Stack Frame的本地变量表引用的对象、Method Area的类静态属性引用的对象(jdk1.8应该归到堆中,1.8之前为永久代中)、方法区常量引用的对象(1.8改把常量池放堆中,而1.8之前方法区以永久代实现,所以放在永久代,物理内存上和堆相近,概念上包含在方法区中,重申1.8的方法区实现为元空间,然后去除永久代,原本永久代的东西只剩类的元信息放在元空间,物理上内存独立于JVM、在本地机器的内存上,而那些常量池、静态变量等转移到堆中)、本地方法栈JNI的引用对象(本地方法栈就是每个线程都各自有一个,调用Native方法的,即非Java方法,而另一个类似的JVM栈则调用java方法,两者都是把方法执行过程中用到的局部变量表、操作数栈、动态链接、方法出口等放到栈帧,然后栈帧入栈、出栈表示方法执行、方法执行完)】}},可达性算法相对复杂一点,但是因为Old区的垃圾回收比较不频繁,所以损失也比较少,同样也因为是垃圾回收比较少,更需要精准的回收之前被忽略的垃圾对象(比如互相引用导致引用计数不为0,但是没有在程序中起到作用的对象)。Old区标记完可达性算法总结出来的可达对象后,把不可达的垃圾对象回收,然后把剩余的可达对象的内存进行整理,整理成连续的空间(并且删除所有刚才临时计算是否可达,用到的标记),这叫作标记-整理(垃圾回收算法),和前面的新生代用到的垃圾回收算法(复制算法)不一样,突出点就是多了内存的碎片整理,但是这样效率会低一点。不过Old区域垃圾回收相较不频繁,所以空间也比较宝贵,值得效率低一点但是空间利用率更高的垃圾回收算法(标记-整理)。

ps:Old垃圾回收提到了GC ROOT对象的判定往往取决于 垃圾回收器指定的规则,垃圾回收器有很多,具体的区别不多做展开介绍,只简单列取几个名称:Serial收集器、Serial Old收集器、ParNew收集器、Parallel Scavenge收集器、 Parallel Old收集器、CMS(Concurrent Mark Sweep)收集器。

--------

--------

下面贴我自己的总结图(点击后放大是没有变形的,建议下载下来或者拖动到新的窗口页面打开。刚补充了一点点,重新贴了图)

发布了60 篇原创文章 · 获赞 6 · 访问量 5499

猜你喜欢

转载自blog.csdn.net/Ashiamd/article/details/104399739