对象是否存活
1、引用计数算法
在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻计数器为零的对象就是不可能再被使用的
优点:效率高,简单
缺点:无法解决循环引用问题
2、可达性分析算法
通过一系列称为“GC Roots”的根对象作为起始节点集,从这些节
点开始,根据引用关系向下搜索,搜索过程所走过的路径称为“引用链”(Reference
Chain),如果某个对象到 GC Roots 间没有任何引用链相连,或者用图论的话来说就是
从 GC Roots 到这个对象不可达时,则证明此对象是不可能再被使用的
在 Java 技术体系里面,固定可作为 GC Roots 的对象包括以下几种:
- ·在虚拟机栈(栈帧中的本地变量表)中引用的对象,譬如各个线程被调用的方法 堆栈中使用到的参数、局部变量、临时变量等。
· - 在方法区中类静态属性引用的对象,譬如 Java 类的引用类型静态变量。 ·在方法区中常量引用的对象,譬如字符串常量池(String Table)里的引用。
- 在本地方法栈中 JNI(即通常所说的 Native 方法)引用的对象。
- Java虚拟机内部的引用,如基本数据类型对应的 Class 对象,一些常驻的异常对象 (比如
NullPointExcepiton、OutOfMemoryError)等,还有系统类加载器。 - 所有被同步锁(synchronized关键字)持有的对象。 ·反映 Java 虚拟机内部情况的 JMXBean、JVMTI中注册的回调、本地代码缓存等
引用类型
- 强引用 —— 代码中的引用赋值
- 软引用 —— 一些还有用,但是非必要的对象,系统内存溢出前,会对其进行二次回收
- 弱引用 —— 在回收的时候必定会被回收
- 虚引用 —— 虚幻引用,只是为了在系统回收该对象时获取一个通知
垃圾收集算法
1、标记清除算法
过程:先标记内存区可回收的对象,标记完成后统一回收掉标记的对象
缺点:1、执行效率不稳定,对象越多,效率越慢
2、回收后存在碎片空间问题
老年代
2、标记复制算法
过程:将内存分片分成两个,留下一个区域不用,当回收时将存活的对象,复制到不用的内存区,在清除掉原来的内存
缺点: 1、会造成空间的浪费(可以调整为8:1:1)
3、标记整理算法
过程:的标记过程仍然与“标记-清除”算法一样,标记结束后所有存活的对象都向内存空间一端移
动,然后直接清理掉边界以外的内存
垃圾收集器
1、Serial 收集器
它进行垃圾收集时,必须暂停
其他所有工作线程,直到它收集结束(新生代)
2、 ParNew 收集器
ParNew 收集器实质上是 Serial 收集器的多线程并行版本 (新生代)
3、Parallel Scavenge 收集器
追求吞吐量的收集器
吞吐量= 运行用户代码时间/(运行代码时间+垃圾收集时间)
4、Serial Old 收集器
erial Old 是 Serial 收集器的老年代版本,它同样是一个单线程收集器,使用标记整理算法。
5、Parallel Old 收集器
Parallel Old 是 Parallel Scavenge 收集器的老年代版本,支持多线程并发收集,基于
标记-整理算法实现。
6、CMS 收集器
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收
集器(老年代-标记清除算法)
7、Garbage First 收集器、
虽然 G1 仍然保留新生代和老年代的概念,但新生代和老年代不再是固定的了,它
们都是一系列区域(不需要连续)的动态集合
G1回收器的步骤:
1、初始标记’
2、并发标记
3、最终标记
4、筛选回收
ThreadLocal 内存泄漏分析
什么是ThreadLocal
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
ThreadLocal的实现原理,每一个Thread维护一个ThreadLocalMap,key为使用弱引用的ThreadLocal实例,value为线程变量的副本。这些对象之间的引用关系如下
,get(),remove()的时候会被清除。
解决方法
- 每次使用完ThreadLocal都调用它的remove()方法清除数据