垃圾收集器和内存分配策略

垃圾收集(Garbage Collection, GC)

  程序计数器、虚拟机栈、本地方法栈这个三个区域随线程而生,随线程而灭,这个几个区域会因为方法结束或线程结束,内存自然就跟随着回收了

  Java堆和方法区的内存分配和回收是动态的,垃圾收集器所关注的就是这部分内存

对象是否已死

  判断对象是否存活有两种方法:1.引用计数算法,2.可达性分析算法

  1. 引用计数算法(Reference Counting)

    给对象一个引用计数器,有一个地方引用她,计数器值加1,引用失效时,计数器值就减1;任何时刻计数器为0的对象是不可能被使用的。

    Java虚拟机里面没有使用引用计数算法管理内存,最主要的原因是它难解决对象之间相互循环引用的问题。

  2. 可达性分析算法(Reachability Analysis)

    主流的商用程序用的都是这个算法

    算法的基本思想是通过一系列称为“GC Roots”的对象作为起点,从这些起点向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用的链相连时,则证明对象是不可用的

    在java种,可以用作GC Roots的对象有以下几种 :

    1.虚拟机栈(栈帧中的本地变量表)中的引用的对象

    2.方法区中的类静态属性引用的对象

    3.方法区中常量引用的对象

    4.本地方法栈中JNI(即一般说的Native方法)引用的对象

引用的分类(JDK1.2后)

  1. 强引用(Strong Reference)

    类似“Object obj = new Object()”这类引用,只要强引用还在,垃圾收集器永远不会回收掉被引用的对象

  2. 软引用(Soft Reference)

    描述有用但非必须的对象。对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中进行第二次回收。如果这次回收还是没有足够的内存,才会抛出内存溢出异常,JDK1.2后,用SoftReference类实现软引用

  3. 弱引用(Weak Reference)

    描述非必须对象,垃圾收集器工作时,不管内存是否足够,都会回收掉只被弱引用关联的对象

  4. 虚引用(Phantom Reference)

    也别称为幽灵引用或者幻影引用,一个对象是否有虚引用,完全不影响其生存时间,也无法通过虚引用取得一个对象实例

    为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知,JDK1.2之后,用PhantomReference类实现虚引用。

对象真正死的时机

  一个对象真正死亡要通过两次标记过程,如果对象在进行可达性分析算法后发现没有GC Root相链接的引用链,那它将会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机认为这两种情况为“没有必要执行”。如果有必要执行,对象会被放置在一个叫做F-Queue的队列中,并稍后由虚拟机自动创立、低优先级的Finalizer线程去触发finalize()方法,但并不承诺会等待finalize()一定会执行完,因为怕finalize()执行太慢,或者死循环。finalize()方法是逃脱回收的最后一次机会,稍后GC会对F-Queue中的对象进行第二次小范围的标记,如果对象在finalize()方法中成功拯救自己----只要重新与引用链上的任何一个对象建立关联即可,那对象就能在第二次标记的时候被移除“即将回收”的集合,否则该对象就真的被回收了。

  finalize()虽然有拯救对象不被回收的机会,但是不建议使用finalize()方法。还有一个对象finzlize()只能被执行一次,也就是只能有一次救自己的机会fang'fa

 回收方法区

  在方法区的垃圾回收性价比比较低,在大量使用反射、动态代理、GCLib等ByteCode框架、动态生成JSP以及OSGi类频繁定义ClassLoader的场景都需要虚拟机具备类卸载的功能,以保证永久代不溢出

  回收的内容包含两部分

  1. 废弃常量,如果一个常量没有对象引用它,它将被回收,必要时会把常量清出常量池。常量池中的其他类(接口)、方法、字段、符号引用也与此类似。

  2. 无用的类。无用的类可以被回收,不是说一定会被回收,HotSpot使用-Xnoclassgc参数控制无用的类是否被回收,还提供了-verbose:class、-XX:+TraceClassLoading、-XX:+TraceClassUnLoading查看类加载和类卸载的信息

    判断一个类是否无用有三个条件:

    1)该类的所有实例被回收(Java堆中不存在该类的任何实例)

    2)加载该类的ClassLoader被回收

    3)该类对应的java.lang.Class对象没有被任何地方引用,无法在任何地方通过反射发给你问该类的方法。

 

posted @ 2018-06-03 23:31  ALittleYuan  阅读(116)  评论(0)    收藏  举报