当须要排查各类内存溢出,内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈的时候,咱们须要对自动化的GC和内存分配实施必要的监控和调节。java
实际上,程序计数器,虚拟机栈和本地方法栈是线程隔离的,每个栈帧中分配的内存在类结构必定的状况下是固定的(这里不考虑JIT优化),所以,只有这几个区域无需考虑内存分配及回收问题,由于方法结束或者线程结束时内存天然被回收了。算法
Java堆及方法区则不同,一个接口的多个实现类需求的内存不同,一个方法中多个分支须要的内存也不同,这部份内存的分配及回收都是动态的,GC关注的也是这部份内存。缓存
给对象添加一个引用计数器,每当有一个地方引用它,那么计数器的值加1,引用失效计数器的值减1。任什么时候刻计数器为零的对象就是不可能被再度使用的。并发
主流的Java虚拟机中没有使用这个方法来管理内存。主要是它很难解决对象之间的相互循环引用的问题。框架
class GCObject {
public Object instance = null;
}
public class GCDemo {
public static void main(String[] args) {
GCObject obj1 = new GCObject(); // 1
GCObject obj2 = new GCObject(); // 2
obj1.instance = obj2; // 3
obj2.instance = obj1; // 4
obj1 = null; // 5
obj2 = null; // 6
}
}
复制代码
以上分为6个步骤:高并发
至此,产生内存泄漏。优化
目前主流的虚拟机都是采用该算法。spa
能够做为GC Roots的对象:线程
上图中的reference1,2,3都是GC Roots对象。虽然实例3,5相互引用(连通),可是GC Roots不可达,这就是GC要回收的垃圾对象。代理
在JDK 1.2以前,Java中引用的定义:若是reference类型的数据中存储的值表明的是另外一块内存的起始地址,就称这块内存表明一个引用。
可是这样很难描述一些引用的“强弱”关系。由于在一些系统的缓存功能中,有一些内存的收集释放须要更为的合理化。因而,引用被分为强引用,软引用,弱引用,虚引用4种。
Object obj = new Object();
这类引用若是存在那么GC永远不会回收这部份内存。SoftReference
类。WeakReference
类。PhantomReference
。在可达性算法中不可达对象并不是必定被GC。对象被GC至少须要两次标记过程,第一次是判断是否有同GC Roots相链接的引用链,若是没有那么判断是否有必要执行finalize()
。
若是有必要执行的话,那么将该对象放置到F-Queue中,而后经过虚拟机建立的一个低优先级的Finalizer线程执行它。
若是在这个过程当中(指被标记须要执行finalize
方法到内存被回收这个时间段以内),对象和任意一个GC Roots相关联,那么对象将会逃逸。
HotSpot中的永久代。 废弃常量以及无用的类。 重点关注无用的类:
一些大量使用反射,动态代理,CGLib技术的框架以及OSGi这类频繁定义ClassLoader的场景须要虚拟机具有类卸载的功能,以保证永久代不会发生内存溢出。
欢迎关注:www.renrunyun.com