Java 中级 学习笔记 2 JVM GC 垃圾回收与算法
程序猿小码 人气:1前言
在上一节的学习中,已经了解到了关于JVM 内存相关的内容,比如JVM 内存的划分,以及JDK8当中对于元空间的定义,最后就是字符串常量池等基本概念以及容易混淆的内容,我们都已经做过一次总结了。不懂的小伙伴再复习复习~
GC
对于GC 这个名词我相信对于学习JAVA的同学,还是多少有了解的。GC 在HotSpot 虚拟机内的具体实现,使我们这节需要了解和学习的地方,而垃圾回收器GC 其工作的最主要的两个场所就是:
- 堆 也就是最大的线程共享区域
- 方法区
确定垃圾的方式
引用计数法
引用计数法,通俗的来说,每个对象都有一个计数器,用于记录这个对象被引用的数量,因为JAVA里面所有的对象都是按照内存地址的引用来使用的,被引用则计数器+1,反之则-1,若这个对象计数器为0,则可大致确认这个对象已经可以被回收了。
可达性算法
可达性分析,是为了解决引用计数法的循环引用问题,GCroots 就好比是一个对象树的根部,而每个对象就可以看做是树状图的上面的树干以及末端叶子,若根部GCroots 与末端或者树枝直接不可达,没有路径,则其成为不可达对象。
不可达对象不等价于可回收对象
不可达对象要抓换为可回收对象,则至少经过两次标记算法。
堆内存
在JVM当中存在这样一块区域,线程共享内存,主要用来存放实例对象和数组,也是垃圾清理GC最活跃的区域
在上一节我们已经学习过了,堆内存又可以按照GC的角度,细分为新生代和老年代,而这两个区域回收算法其实是各有千秋的。请听我细细道来~
GC分代收集算法
分代收集算法是当代VM常用的对象收集算法,通俗的讲,就是把堆内存分为新生代和老年代,在不同的区域内执行不同算法进行垃圾对象的清理与回收,其实分代回收算法算是一个父类,具体的算法还是我们下面要说的:
- 新生代复制算法
- 老年代标记整理算法
新生代
- 复制算法
- Minor GC
- 简单、效率好,不易产生碎片
新生代作为堆内存里面最为活跃的一块内存区域,其主要负责新对象的产生,通过Minor GC清理内存空间,将到达年龄的对象送至老年代。
复制算法
复制算法,将区域的内存划分为两块,每次只是使用其中的一块。当一边的内存存满后,将这边的活跃对象全部复制到另一边,清空这一边的内存。
画个图来理解一下:
这幅图就很生动了,简单的总结一下就是:
复制--->清空---->互换
着其实和我们上一节当中就简单提了一下,同学们是否还记得?那我就再次浮现一下上次画过的图,其实就是Minor GC 最主要的工作方式。
将这幅图和我们这次的结果结合起来,就多了一块内存区域,其实多出来的TO区域 不就充当了一个缓存的过程嘛,最后还是把内存交出去,作为下一次的From区域,是一样的。
老年代
- 标记整理算法
- MajorGC
在学习老年带的整理算法之前,我们首先需要了解一下标记清除算法。因为这个算法是标记整理算法的前生,需要先了解标记清除算法以及其功能性特点,才能理解标记整理算法的由来。
标记清除算法
其实可以从字面意思上理解到这个算法的意思,那就是:先标记而后进行清除嘛,其实就是这样的,先标记,而后清除。画个图,来理解一下。
这个算法就是这么简单粗暴,标记出来之后直接给你干掉!
特点:碎片化内存块严重
标记整理算法
标记整理算法就其实是这两个算法的结合,标记后不是清理,而是将这些标记的可以回收对象,活跃对象移到另外一边,清除可以回收的一侧对象。
标记、整理、最后再清理
小结
通过这一节的学习,以及结合上一节的内容。应该了解到java vm 的内存分布区域以及在最重要的堆里面进行的分代回收算法的基本概念,以及两个最重要的算法,新生代复制算法,老年代标记整理算法 这些也算是最面试当中经常出现的内容,还是需要熟悉。
对于具体的垃圾回收器这里暂时就不做那么深的说明了,暂时了解到这儿,越深入,对于刚开始的人越迷糊啊,等具体用到了再了解深入也不急。
参考
- 知乎大佬关于引用计数法:https://www.zhihu.com/question/21539353
- 微信公众号:Java 极客技术
加载全部内容