1.垃圾回收概述
Java内存运行时程序计数器、虚拟机栈、本地方法栈三个区域随着线程而生随着线程而灭,所以这几个区域的内存分配和回收都有确定性,方法和线程结束的时候内存就自动回收了。
而Java堆和方法区则不一样,一个接口的多个实现类需要的内存不一样,一个方法的多个分支需要的内存也不一样,只有在 程序运行期间才会知道创建哪些对象,这些内存的分配和回收都是动态的,垃圾收集器关注的内存就是这部分。
2.对象存活判定算法
引用计数算法:
给对象添加一个引用计数器,当对象被引用时,计数器加1,当引用失效时,计数器数值就减1,直至计数器为0时,该对象不能再被使用(引用计数器值为0——>垃圾)。
实现简单高效,但是无法解决对象之间循环引用的问题。
可达性分析算法(根搜索算法):
这种算法是以“GC Roots”为起始节点,向下搜索对象,走过的路径称为引用链,如果一个对象到GC Roots之间没有引用链,那么即判定这个对象不可用,可回收。
而在Java语言中发可以作为GC Roots的对象包括以下几种:
虚拟机栈(本地变量表)中引用的对象,
方法区中类静态属性引用的对象,
方法区常量引用的对象,
本地方法栈中JNI(Native方法)引用的对象。
引用:
不管是引用计数算法的引用计数还是可达性算法的引用链均与对象引用有关。
引用的定义:如果reference类型的数据中存储的数值代表的是另一块内存的起始地址,那么久成这块内存代表着一个引用。
JDK1.2后将引用分为了四种
强引用:代码中普遍存在的,类似“Object obj = new Object()”这类的引用,只要强引用存在,不会被回收。
软引用:用来描述一些还有用但是不必须的对象,软引用关联的对象,在发生内存溢出异常之前,会将其进行第二次垃圾回收。
JDK1.2后用SoftReference类实现软引用。
弱引用:用来描述非必需的对象,其关联的对象只能生存到下次垃圾收集之前。垃圾收集时无论当前内存是否足够,都会被清理。
JDK1.2后用weakReference类实现软引用。
虚引用:也叫幽灵引用和幻影引用,是最弱的一种引用关系。设置这个引用的唯一目的是其关联的对象被垃圾回收时收到一个系统通知。
JDK1.2后用PhantomReference类实现软引用。
PS:
可达性算法不可达的对象也并非是“非死不可”的,判断一个对象死亡有两次标记过程,其一是对对象进行可达性分析,若发现该对象与GC Roots之间没有引用链,则会对其进行第一次标记并且进行筛选,而筛选的条件是判断该对象是否有必要执行finalize()方法;若该对象被判定为需要执行finalize()方法,则会把对象放入F-Qeue的队列中,而收集器会对F-Qeue队列中的对象进行第二次标记。
此时对象想要在finalize()方法中拯救自己,只要重新与引用链的任意一个对象建立起练习即可(例如把自己this关键字赋值给某个变量或者对象的成员变量),这时该对象会在第二次标记的时候移除出队列。
回收方法区:
方法区回收的主要内容是:废弃常量和无用的类。
判断废弃常量:当前系统中没有任何对象引用常量池中的对象,则为废弃常量。
判断无用的类:
①该类的所有实例都被回收,Java堆中不存在该类的任何实例。
②加载该类的ClassLoader已经被回收。
③加载对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。