JVM学习笔记7:垃圾收集(对象的存活及引用)

一 概述

    简单的说内存中已经不再被使用到对象(非存活对象)或方法所占用的的空间就是垃圾。将这部分空间释放,即为垃圾回收。

    由于PC寄存器(程序计数器)java栈本地方法栈 这3个区域都是随线程生线程灭的,因此这几个区域的内存分配和回收都具备确定性,当方法或线程结束时内存自然就回收了。

   java堆方法区在一个接口中的多个实现类所需要的内存可能不一样,一个方法中多个分支所需要的内存也可能不一样,我们只有在程序运行期间时才能知道会创建那些对象,所以这部分的内存分配都是动态的。所以垃圾收集器所操作的内存即为java堆和方法区这两部分空间所占用的内存。

     


 

二 如何判断对象是否存活

  1.引用计数法

       给对象中添加一个应用计数器,没当一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1。

任何时刻计数器为0的对象就是不可能再被使用的。

  优点:实现简单、效率高
  缺点:不能解决对象之间相互循环引用的问题

java虚拟机里没有选用引用计数器算法来管理内存,其中最主要的原因是它很难解决对象直接相互循环引用的问题。

二.可达性分析算法

       通过一系列的称为(GC Roots)的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots 没有任何引用链相连(用图论的话来说,就是从GC Roots 到这个对象不可达)时,则证明此对象是不可用的。

JVM学习笔记7:垃圾收集(对象的存活及引用)_第1张图片可作为GC Roots的对象包括:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
  • 方法区类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI(即一般说的Native方法)引用的对象

         a.HotSpot使用了一组叫做OopMap的数据结构达到准确式GC的目的:在类加载完成的时候,JVM会计算出当
前对象在哪个偏移位置上会有什么引用,这样GC扫描的时候可以很快得到引用的信息。
       b.在OopMap的协助下,JVM可以很快的做完GC Roots枚举。但是JVM并没有为每一条指令生成一个OopMap,
否则会需要非常多的额外空间,反而会增加GC回收成本。因此只在特定的位置才会记录这些信息,这些
“特定的位置”被称为安全点(SafePoint),即当前线程执行到安全点后才允许暂停进行GC。
          c.如果一段代码中,对象引用关系不会发生变化,这个区域中任何地方开始GC都是安全的,那么这个区域
称为安全区域(Safe Region)。安全区域可看做是扩展了的安全点。
 

1 引用

     JDK1.2之后,java对引用的概念进行了扩充,将引用分为强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4种,这4中引用强度依次逐渐减弱。

  •     强引用就是指在程序代码之中普遍存在的,类似“Object obj = new Object()” 这类引用,只要强引用还存在,垃圾收集器永远不会回收掉引用 的对象。
  • 软引用是用来描述一些还有用但非必须的对象。对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中进行第二次回收。如果这次回收之后还没有足够的内存,才会抛出内存溢出异常。(系统的本地缓存可以考虑通过软引用来实现通过SoftReference类来实现软引用。
  • 弱引用是用来描述非必需的对象。但是它的强度比软引用要更弱一些,弱引用关联的对象只能生存到下一次垃圾收集发生之前。无论当前内存是否足够,都会回收掉只被弱引用关联的对象,通过WeakReference类来实现弱引用
  • 虚引用也称为幽灵引用或者幻影引用,一个对象是否有虚引用存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为对象设置虚引用的唯一目的是能在这个对象被收集器回收时收到一个系统通知。通过PhantomReference来实现虚引用。

2 判断类无用的条件

        1:JVM中该类的所有实例都已经被回收
        2:加载该类的ClassLoader已经被回收
        3:没有任何地方引用该类的Class对象
       4:无法在任何地方通过反射访问这个类


3 GC类型

1:MinorGC:发生在新生代的收集动作
2:MajorGC / Full GC:发生在老年代的GC,通常伴随至少一次的MinorGC
 

4 Stop-The-World


     STW 是java中的全局停顿现象,为了实现GC。可达性分析算法会使整个分期期间整个执行系统看起来像是冻结在某个时间点上,不可以出现分析过程中对象引用关系还在不断变化的情况,改点不满足的话分析结果的准确性就无法得到保证。这点是导致GC进行时必须停顿所有Java执行线程的其中一个重要原因。
     


5串行、并行、并发收集


1:串行收集:GC单线程内存回收、会暂停所有的用户线程
2:并行收集:多个GC线程并发工作,此时用户线程是暂停的
3:并发收集:用户线程和GC线程同时执行(不一定是并行,可能交替执行),不需要停顿用
户线程
4:Serial是串行的,Parallel是并行的,CMS是并发的
 


 

你可能感兴趣的:(JVM)