java gc 随记
gc为garbage collection的缩写,中文翻译为垃圾回收。垃圾为不在使用的实例、变量,回收为释放垃圾所占用的内存空间。
学习过的C语言、C++语言,是没有垃圾回收机制的,因此需要软件工程师通过编写代码释放无用变量或实例占用的内存空间。人为操作会存在遗漏的问题,因此有时会出现内存泄露等问题。
jvm中的堆是主要的内存分配区域,jvm的gc工作区域也主要在这一片内存中。
如何判断哪些内存需要回收?
引用计数法
通过记录实例变量被引用的次数,可知不再使用的内存。但是如果存在交叉引用的情况,就会出现内存泄露的问题。
可达性分析法
通过一系列称为GC Roots的实例作为起点,逐步向下递归搜索各自引用的实例,搜索所走过的路径称为引用链。当一个实例不在GC Roots为起点的引用链时,证明此实例不再被使用,其内存空间可被回收。
GCRoots包含四个部分:
- 虚拟机栈本地变量表中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI(Native方法)引用的对象
四种引用方式:强引用,软引用,弱引用,虚引用
如何垃圾回收?
标记-清除:两个阶段,会产生内存碎片。
标记-复制:内存空间分为两个部分,将标记后存活的实例复制到另一片内存空间中,另一片内存空间清空。
标记-整理:改变标记-清除算法的内存碎片问题,将存活实例整理在一起。
分代整理:分为年轻代内存空间和老年代内存空间,年轻代内存中的对象能存活下来的很少,使用标记-复制算法,年老代内存中的对象内存储下来的较多,使用标记-清除或标记-整理算法。
由谁执行垃圾回收?
serial收集器
使用单线程标记-复制算法进行垃圾回收,程序会暂停。
ParNew收集器
Serial收集器的多线程版本,程序依然会暂停。
Parallel Scavenge收集器
类似ParNew收集器,可动态调节垃圾回收时的停顿时间,吞吐量。程序依然暂停,但暂停时间可预估。
Serial Old收集器、Parallel Old收集器
单线程版、多线程版,标记-清除算法,程序会暂停
CMS收集器
分四个阶段
(1). 初始标记,标记GCRoots能直接关联到的对象,时间很短。程序暂停
(2). 并发标记,进行GCRoots Tracing(可达性分析)过程,时间很长。程序不暂停
(3). 重新标记,修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,时间较长。程序暂停
(4). 并发清除,回收内存空间,时间很长。程序不暂停