JAVA-GC机制

#1、GC基本原理 GC(Garbage Collection),是JAVA/.NET中的垃圾收集器。
Java是由C++发展来的,它摈弃了C++中一些繁琐容易出错的东西,引入了计数器的概念,其中有一条就是这个GC机制(C#借鉴了JAVA)。程序员

编程人员容易出现问题的地方,忘记或者错误的内存回收会致使程序或系统的不稳定甚至崩溃,Java提供的GC功能能够自动监测对象是否超过做用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操做方法。因此,Java的内存管理实际上就是对象的管理,其中包括对象的分配和释放。算法

对于程序员来讲,分配对象使用new关键字;释放对象时,只要将对象全部引用赋值为null,让程序不可以再访问到这个对象,咱们称该对象为"不可达的".GC将负责回收全部"不可达"对象的内存空间。编程

对于GC来讲,当程序员建立对象时,GC就开始监控这个对象的地址、大小以及使用状况。一般,GC采用有向图的方式记录和管理堆(heap)中的全部对象。经过这种方式肯定哪些对象是"可达的",哪些对象是"不可达的".当GC肯定一些对象为"不可达"时,GC就有责任回收这些内存空间。可是,为了保证 GC可以在不一样平台实现的问题,Java规范对GC的不少行为都没有进行严格的规定。例如,对于采用什么类型的回收算法、何时进行回收等重要问题都没有明确的规定。所以,不一样的JVM的实现者每每有不一样的实现算法。这也给Java程序员的开发带来行多不肯定性。本文研究了几个与GC工做相关的问题,努力减小这种不肯定性给Java程序带来的负面影响。网络

#2、GC分代划分 JVM内存模型中Heap区分两大块,一块是 Young Generation,另外一块是Old Generation 。
输入图片说明函数

  1. 在Young Generation中,有一个叫Eden Space的空间,主要是用来存放新生的对象,还有两个Survivor Spaces(from、to),它们的大小老是同样,它们用来存放每次垃圾回收后存活下来的对象。
  2. 在Old Generation中,主要存放应用程序中生命周期长的内存对象。
  3. 在Young Generation块中,垃圾回收通常用Copying的算法,速度快。每次GC的时候,存活下来的对象首先由Eden拷贝到某个SurvivorSpace,当Survivor Space空间满了后,剩下的live对象就被直接拷贝到OldGeneration中去。所以,每次GC后,Eden内存块会被清空。
  4. 在Old Generation块中,垃圾回收通常用mark-compact的算法,速度慢些,但减小内存要求。
  5. 垃圾回收分多级,0级为所有(Full)的垃圾回收,会回收OLD段中的垃圾;1级或以上为部分垃圾回收,只会回收Young中的垃圾,内存溢出一般发生于OLD段或Perm段垃圾回收后,仍然无内存空间容纳新的Java对象的状况。

#3、增量式GC 增量式GC(Incremental GC),是GC在JVM中一般是由一个或一组进程来实现的,它自己也和用户程序同样占用heap空间,运行时也占用CPU。性能

当GC进程运行时,应用程序中止运行。所以,当GC运行时间较长时,用户可以感到Java程序的停顿,另一方面,若是GC运行时间过短,则可能对象回收率过低,这意味着还有不少应该回收的对象没有被回收,仍然占用大量内存。所以,在设计GC的时候,就必须在停顿时间和回收率之间进行权衡。一个好的GC实现容许用户定义本身所须要的设置,例若有些内存有限的设备,对内存的使用量很是敏感,但愿GC可以准确的回收内存,它并不在乎程序速度的快慢。另一些实时网络游戏,就不可以容许程序有长时间的中断。 增量式GC就是经过必定的回收算法,把一个长时间的中断,划分为不少个小的中断,经过这种方式减小GC对用户程序的影响。虽然,增量式GC在总体性能上可能不如普通GC的效率高,可是它可以减小程序的最长停顿时间。.net

Sun JDK提供的HotSpot JVM就能支持增量式GC。HotSpot JVM缺省GC方式为不使用增量GC,为了启动增量GC,咱们必须在运行Java程序时增长-Xincgc的参数。 HotSpot JVM增量式GC的实现是采用Train GC算法,它的基本想法就是:将堆中的全部对象按照建立和使用状况进行分组(分层),将使用频繁高和具备相关性的对象放在一队中,随着程序的运行,不断对组进行调整。当GC运行时,它老是先回收最老的(最近不多访问的)的对象,若是整组都为可回收对象,GC将整组回收。这样,每次GC运行只回收必定比例的不可达对象,保证程序的顺畅运行。设计

#4、finalize finalize 是位于Object类的一个方法code

protected void finalize() throws Throwable { }

该方法的访问修饰符为protected,因为全部类为Object的子类,所以用户类很容易访问到这个方法。对象

因为,finalize函数没有自动实现链式调用,咱们必须手动的实现,所以finalize函数的最后一个语句一般是 super.finalize()。经过这种方式,咱们能够实现从下到上实现finalize的调用,即先释放本身的资源,而后再释放父类的资源。根据Java语言规范,JVM保证调用finalize函数以前,这个对象是不可达的,可是JVM不保证这个函数必定会被调用。另外,规范还保证finalize函数最多运行一次。

不建议使用finalize:

  • GC为了可以支持finalize函数,要对覆盖这个函数的对象做不少附加的工做。
  • 在finalize运行完成以后,该对象可能变成可达的,GC还要再检查一次该对象是不是可达的。所以,使用 finalize会下降GC的运行性能。
  • 因为GC调用finalize的时间是不肯定的,所以经过这种方式释放资源也是不肯定的。

一般,finalize用于一些不容易控制、而且很是重要资源的释放,例如一些I/O的操做,数据的链接。这些资源的释放对整个应用程序是很是关键的。在这种状况下,程序员应该以经过程序自己管理(包括释放)这些资源为主,以finalize函数释放资源方式为辅,造成一种双保险的管理机制,而不该该仅仅依靠finalize来释放资源。

#5、强引用、弱引用、软引用、虚引用 Java 4种引用的级别由高到低依次为:
强引用 > 软引用 > 弱引用 > 虚引用

四种引用在垃圾回收时的区别:
输入图片说明

参考文献:

https://my.oschina.net/ydsakyclguozi/blog/404389
http://blog.csdn.net/ithomer/article/details/6252552

相关文章
相关标签/搜索