1.概述
java源文件通过编译为java字节码文件,然后通过类加载器加载文件中各个类字节码,然后通过jvm执行。在这个过程中需要一个空间用于存储程序执行期间需要的数据和信息。这个空间叫做运行时数据区。
1.对象存活判定算法
1.1 java 引用的四种类型
a. 强引用(StrongReference)Object object = new Object()
具有强引用的对象不会被gc,即便内存不足jvm也不会回收强引用的对象。
b. 软引用(SoftReference)
当内存不足时会被gc,如果回收后内存还是不足时,会抛出OOM异常。
c. 弱引用(weakReference)
会存活到下一次垃圾收集前。
d. 虚引用(PhantomReference)
任何时候都可能被gc
1.2 引用计数算法
每个对象都有一个计数器,当对象被引用一次时,计数器会加1,当对象引用失效一次则计数器就减1,当计数器为0时,就可以被gc了。
缺点:无法解决对象之间相互循环引用的问题。
1.3 可达性算法(GC Roots Tracing)
从称为GC Roots的对象做起始位置,开始往下搜索,连接到的路径叫做引用链。当有一个对象无法连接到引用链时,它就是不可用的,会被GC掉。
GC Roots的类型:
(1)java栈(栈帧中局部变量表)中引用的对象
(2)方法区中类静态属性引用的对象
(3)方法区中常量引用的对象
(4)本地方法栈中JNI引用的对象
注意:对象没有连接到引用链时被第一次标记,并不是真正的死亡。有两种情况需要判断:
情况一:没有覆盖finalize方法或者虚拟机已经调用过它的finaliza方法,就会被直接回收。
情况二:将对象放置在一个F-Queue队列中,由虚拟机开启一条线程运行这个对象的finalize(),如果对象在运行finaliza()的过程中重新连接上引用链的话,会被第二次标记逃过GC,否则会被回收。
1.4 方法区回收
在方法区中主要回收的是: 废弃常量 和 无用的类
废弃常量:没有被引用的常量
无用的类:同时满足三个条件
a.该类的实例已经被回收
b.加载该类的加载器已经被回收
c.该类的Class对象没有被引用,并且无法通过反射访问到该类的方法。
2.垃圾回收算法
2.1标记-清除算法
标记出所有需要回收的对象,然后清除所有被标记的对象。
缺点:会造成内存碎片,内存不连续。
2.2 标记-整理算法
标记出所有需要回收的对象,然后进行整理,将存活的对象都向一端移动,最后清除掉标记的对象。
优点:不会产生过多的碎片
2.3 复制算法
把可用内存按容量划分为大小相等的两块,每次只使用其中一块。当这一块的内存用尽后,把还存活着的对象复制到另外一块上,再将这一块内存空间清理掉。
优点:每次都是对整个版区进行内存回收,无需考虑内存碎片的情况。
缺点:每次可使用的内存缩小为原来的一半,内存使用率低。
2.4 分代收集算法
这种算法是目前大部分jvm的垃圾收集器采用的算法。
核心思想是根据对象存活的声明周期将内存划分为若干个不同的区域,分为老年代和新生代。
老年代的特点是每次垃圾收集器只有少量对象需要被回收,而新生代的特点是每次垃圾回收器都有大量对象需要被回收。可以根据特点来使用合适的收集算法。
老年代:对象存活率老。使用标记-清除算法或标记-整理算法。
新生代:使用复制算法,只需复制少量存活对象即可。
以上图片均在网上找,若有冒犯敬请原谅。