程序计数器、虚拟机栈、本地方法栈随线程而生、随线程而灭
堆和方法区
一个接口的多个实现类所需的内存不一样,一个方法的多个执行分支所需的内存不一样,在程序执行过程中动态地分配和回收内存
(1)引用计数法
引用计数器,有一个地方引用,计数器的值加一
很难解决对象之间循环引用的问题
(2)可达性分析
GCRoots
一个对象有没有到GCRoots的引用链
可作为GCRoots的对象:虚拟机栈中引用的对象
方法区类静态属性引用的对象
方法区常量引用的对象
本地方法栈中JNI(java native interface)引用的对象
(1)强引用 垃圾回收器永远不会回收 Object obj = new Object();
(2)软引用 还有用但不必需 在将要发生内存溢出之前,把软引用对象例如回收范围进行二次回收,如果回收之后还没有足够内存,才抛出内存溢出异常
(3)弱引用 非必需对象 弱引用关联的对象只能存活到下一次垃圾回收之前,无论内存是否足够,都回收弱引用管理的对象
(4)虚引用 无法通过虚引用获得对象的实例,设置虚引用,在该对象被垃圾回收之时,收到一个系统通知
不可达对象,生存还是死亡?
如果对象在可达性分析之后,没有到GCRoots的引用链------不可达对象
对不可达对象,两次标记过程:
(1)对不可达对象进行第一次标记,检查是否有必要执行finalize()方法
如果对象没有覆盖finalize方法 或者 该对象的finalize方法已经被虚拟机调用过(任何对象的finalize方法只会被调用一次) 认为没有必要执行finalize方法
如果有必要执行finalize方法
将对象放在F-Queue队列中,并稍后由一个虚拟机建立的、低优先级的Finalizer线程执行它(Finalizer线程会触发finalize方法,但不一定会等待该方法执行完毕)
(2)对F-Queue队列中的对象进行第二次标记,检查是否在finalize方法中自救成功
如何自救?将自己重新与引用链上的任何一个对象建立关联
如果自救成功
该对象将被移出即将回收的集合
判断一个类是否是无用的类?
(1)java堆中不存在该类的任何实例
(2)该类的classloader已经被回收
(3)该类对应的java.lang.Class类的实例没有在任何地方被引用,无法在任何地方通过反射访问类的成员
垃圾回收算法
(1)标记-清除
内存碎片效率低
(2)复制
无内存碎片
浪费部分内存空间
新生代 采用复制算法回收:Eden: Survivor:Survivor = 8:1:1(10%的空间浪费)
(3)标记-整理
没有内存碎片
(4)分代收集
新生代:复制
老年代:标记-整理 标记-清除