java垃圾回收机制介绍_第1页
java垃圾回收机制介绍_第2页
java垃圾回收机制介绍_第3页
java垃圾回收机制介绍_第4页
java垃圾回收机制介绍_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Java的堆是一个运行时数据区,类的实例(对象)从中安排空间。Java虚拟机

(JVM)的堆中储存着正在运行的应用程序所建立的全部对象,这些对象通过new、

newarray>anewarray和multianewarray等指令建立,但是它们不需要程序代玛来

显式地释放。一般来戴,堆的是由垃圾回收来负责的,尽管JVM标准并不要求特

别的垃圾回收技术,甚至根本就不需要垃圾回收,但是由于内存的有限性,JVM在

实现的时候都有一个由垃圾回收所治理的堆。垃圾回收是一种动态存储治理技术,

它自动地释放不再被程序引用的对象,依据特定的垃圾收集算法来实现资源自动回

收的功能。

垃圾收集的意义

在C++中,对象所占的内存在程序完毕运行之前始终被占用,在明确释放之前

不能安排给其它对象;而在Java中,当没有对象引用指向原先安排给某个对象的

内存时,该内存便成为垃圾。JVM的一个系统级线程会自动释放该内存块。垃圾收

集意味着程序不再需要的对象是“无用信息“,这些信息将被丢弃。当一个对象不

再被引用的时候,内存回收它占据的空间,以便空间被后来的对象使用。事实上,

除了释放没用的对象,垃圾收集也可以去除内存记录碎片。由于创立对象和垃圾收

集器释放丢弃对象所占的内存空间,内存会消灭碎片。碎片是安排给对象的内存块

之间的空闲内存洞。碎片整理将所占用的堆内存移到堆的一端,JVM将整理出的内

存安排给的对象。

垃圾收集能自动释放内存空间,减轻编程的负担。这使Java虚拟机具有一些

优点。首先,它能使编程效率提高。在没有垃圾收集机制的时候,可能要花很多时

间来解决一个难懂的存储器问题。在用Java语言编程的时候,靠垃圾收集机制可

大大缩短时间。其次是它保护程序的完整性,垃圾收集是Java语言安全性策略的

一个重要部份。

垃圾收集的一个潜在的缺点是它的开销影响程序性能。Java虚拟机必需追踪运

行程序中有用的对象,而且最终释放没用的对象。这一个过程需要花费处理器的时

间。其次垃圾收集算法的不完备性,早先承受的某些垃圾收集算法就不能保证100%

收集到全部的废弃内存。固然随着垃圾收集算法的不断改进以及软硬件运行效率的

不断提升,这些问题都可以迎刃而解。

垃圾收集的算法分析

Java语言标准没有明确地说明JVM使用哪种垃圾回收算法,但是任何一种垃

圾收集算法一般要做2件根本的事情:(1)觉察无用信息对象;(2)回收被无用对

象占用的内存空间,使该空间可被程序再次使用。

大多数垃圾回收算法使用了根集(rootset)这个概念;所谓根集就量正在执行的

Java程序可以访问的引用变量的集合(包括局部变量、参数、类变量),程序可以使

用引用变量访问对象的属性和调用对象的方法。垃圾收集首选需要确定从根开头哪

些是可达的和哪些是不行达的,从根集可达的对象都是活动对象,它们不能作为垃

圾被回收,这也包括从根集间接可达的对象。而根集通过任意路径不行达的对象符

合垃圾收集的条件,应当被回收。下面介绍几个常用的算法。

1、引用计数法(ReferenceCountingCollector)

引用计数法是唯一没有使用根集的垃圾回收的法,该算法使用引用计数器来区

分存活对象和不再使用的对象。一般来说,堆中的每个对象对应一个引用计数器。

当每一次创立一个对象并赋给一个变量时,引用计数器置为1。当对象被赋给任意

变量时,引用计数器每次加1当对象出了作用域后(该对象丢弃不再使用),引用计

数器减1,一旦引用计数器为0,对象就满足了垃圾收集的条件。

基于引用计数器的垃圾收集器运行较快,不会长时间中断程序执行,适宜地必

需实时运行的程序。但引用计数器增加了程序执行的开销,由于每次对象赋给的变

量,计数器加1,而每次现有对象出了作用域生,计数器减1。

2、tracing算法(TracingCollector)

tracing算法是为了解决引用计数法的问题而提出,它使用了根集的概念。基于

tracing算法的垃圾收集器从根集开头扫描,识别出哪些对象可达,哪些对象不行达,

并用某种方式标记可达对象,例如对每个可达对象设置一个或多个位。在扫描识别

过程中,基于tracing算法的垃圾收集也称为标记和去除(mark-and・sweep)垃圾收集

器.

3、compacting算法(CompactingCollector)

为了解决堆碎片问题,基于tracing的垃圾回收吸取了Compacting算法的思想,

在去除的过程中,算法将全部的对象移到堆的一端,堆的另一端就变成了一个相邻

的空闲内存区,收集器会对它移动的全部对象的全部引用进展更,使得这些引用在

的位置能识别原来的对象。在基于Compacting算法的收集器的实现中,一般增加

句柄和句柄表。

4、copying算法(CopingCollector)

该算法的提出是为了抑制句柄的开销和解决堆碎片的垃圾回收。它开头时把堆

分成一个对象面和多个空闲面,程序从对象面为对象安排空间,当对象满了,

基于coping算法的垃圾收集就从根集中扫描活动对象,并将每个活动对象复制到

空闲面(使得活动对象所占的内存之间没有空闲洞),这样空闲面变成了对象面,原

来的对象面变成了空闲面,程序会在的对象面中安排内存。

一种典型的基于coping算法的垃圾回收是stop・and-copy算法,它将堆分成对

象面和空闲区域面,在对象面与空闲区域面的切换过程中,程序暂停执行。

5、generation算法(GenerationalCollector)

stop-and-copy垃圾收集器的一个缺陷是收集器必需复制全部的活动对象,这增

加了程序等待时间,这是coping算法低效的缘由。在程序设计中有这样的规律:多

数对象存在的时间比较短,少数的存在时间比较长。因此,generation算法将堆分成

两个或多个,每个子堆作为对象的一代(generation)。由于多数对象存在的时间比较

短,随着程序丢弃不使用的对象,垃圾收集器将从最年轻的子堆中收集这些对象。在分

代式的垃圾收集器运行后,上次运行存活下来的对象移到下一最高代的子堆

中,由于老一代的子堆不会常常被回收,因而节约了时间。

6、adaptive算法(AdaptiveCollector)

在特定的状况卜,一些垃圾收集算法会优于其它算法。基于Adaptive算法的垃

圾收集器就是监控当前堆的使用状况,并将选择适当算法的垃圾收集器。

透视Java垃圾回收

1、命令行参数透视垃圾收集器的运行

2、使用System.gc可以不管JVM使用的是哪一种垃圾回收的算法,都可以恳

求Java的垃圾回收。在命令行中有一个参数・verbosegc可以查看Java使用的堆内

存的状况,它的格式如下:

java-verbosegcclassfile

可以看个例子:

classTestGC

publicstaticvoidmain(Slring[]args)

newTestGC;Systcm.gc;

System.runFinaiization;

在这个例子中,一个的对象被创立,由于它没有使用,所以该对象快速地变为

可达,程序编译后,执行命令:java-verbosegcTestGC后结果为:

(而且确定不能直接调用finalize,所以应尽量避开用它)。假设期望执行除释放

存储空间之外的其他某种形式的去除工作,照旧必需调用Java中的一个方法。它

等价于C++的破坏器,只是没后者便利。

下面这个例子向大家呈现了垃圾收集所经受的过程,并对前面的陈述进展了总

结。

classChair{

staticbooleangcrun=false;

staticbooleanf=false;

staticintcreated=0;

staticintfinalized=0;

inti;

Chair{

i=++created;

if(created==47)

System.out.println(aCreated47

)

protectedvoidfinalize

{if(!gcrun){

gcrun=true;

Systpm.nut.printlnfaBeginningtnfinalizeafter"+created+"Chairshave

beencreated");

)

if(i==47){

System.out.printlnfFinalizingChair#47,“+aSettingflagtostopChair

creation

f=true;

)

finalized++;

if(finalized>=created)

System.out.println("AH+finalized+finalized

)

)

publicclassGarbage{

publicstaticvoidmain(String[]args)

{if(args.length==0){

System.err.println(Usage:\n"+“javaGarbagebefore\nor:\n"+“java

Garbageafter");

return;

)

while(!Chair.f)

{newChair;

newString(^Totakeupspace

)

System.out.printlnfwAfterallChairshavebeencreated:\n"+wtotalcreated=

a

+Chair.created+

",totalflnalized="+

Chair.finalized);

if(args[O].equals(abefore")){

System.out.println(agc:“);

System.gc;

System.out.println(^runFinalization:

System.runFinalization;

)

System.out.println(Mbye!

if(args[O].equals(after"))

System.runFinalizersOnExit(true);

)

)

2、tracing算法(TracingCollector)

tracing算法是为了解决引用计数法的问题而提出,它使用了根集的概念。基于

tracing算法的垃圾收集器从根集开头扫描,识别出哪些对象可达,哪些对象不行达,

并用某种方式标记可达对象,例如对每个可达对象设置一个或多个位。在扫描识别

过程中,基于tracing算法的垃圾收集也称为标记和去除(mark・and・sweep)垃圾收集

器.

3、compacting算法(CompactingCollector)

为了解决堆碎片问题,基于tracing的垃圾回收吸取了Compacting算法的思想,

在去除的过程中,算法将全部的对象移到堆的一端,堆的另一端就变成了一个相邻

的空闲内存区,收集器会对它移动的全部对象的全部引用进展更,使得这些引用在

的位置能识别原来的对象。在基于Compacting算法的收集器的实现中,一般增加

句柄和句柄表。

4、copying算法(CopingCollector)

该算法的提出是为了抑制句柄的开销和解决堆碎片的垃圾回收。它开头时把堆

分成一个对象面和多个空闲面,程序从对象面为对象安排空间,当对象满了,

基于coping算法的垃圾收集就从根集中扫描活动对象,并将每个活动对象复制到

空闲面(使得活动对象所占的内存之间没有空闲洞),这样空闲面变成了对象面,原

来的对象面变成了空闲面,程序会在的对象面中安排内存。

一种典型的基于coping算法的垃圾回收是stop・and・copy算法,它将堆分成对

象面和空闲区域面,在对象面与空闲区域面的切换过程中,程序暂停执行。

5、generation算法(GenerationalCollector)

stop-and-copy垃圾收集器的一个缺陷是收集器必需复制全部的活动对象,这增

加了程序等待时间,这是coping算法低效的缘由。在程序设计中有这样的规律:多

数对象存在的时间比较短,少数的存在时间比较长。因此,generation算法将堆分

成两个或多个,每个子堆作为对象的一代(generation)。由于多数对象存在的时间比

较短,随着程序丢弃不使用的对象,垃圾收集器将从最年轻的子堆中收集这些对象。在

分代式的垃圾收集器运行后,上次运行存活下来的对象移到下一最高代的子堆

中,由于老一代的子堆不会常常被回收,因而节约了时间。

6、adaptive算法(AdaptiveCollector)

在特定的状况下,一些垃圾收集算法会优于其它算法。基于Adaptive算法的垃

圾收集器就是监控当前堆的使用状况,并将选择适当算法的垃圾收集器。

上面这个程序创立了很多Chair对象,而且在垃圾收集器开头运行后的某些时

候,程序会停顿创立Chairo由于垃圾收集器可能在任何时间运行,所以我们不能

准确知道它在何时启动。因此,程序用一个名为gcrun的标记来指出垃圾收集器是

否已经开头运行。利用其次个标记f,Chair可告知main它应停顿对象的生成。这

两个标记都是在finalize内部设置的,它调用于垃圾收集期间。另两个static变量

-created以及finalized•■分别用于跟踪已创立的对象数量以及垃圾收集器已进展完

收尾工作的对象数量。最终,每个Chair都有它自己的(非static)inti,所以能跟

踪了解它具体的编号是多少。编号为47的Chair进展完收尾工作后,标记会设为

true,最终完毕Chair对象的创立过程。

关于垃圾收集的几点补充

经过上述的说明,可以觉察垃圾回收有以下的几个特点:

(1)垃圾收集发生的不行预知性:由于实现了不同的垃圾收集算法和承受了

不同的收集机制,所以它有可能是定时发生,有可能是当消灭系统空闲CPU资源

时发生,也有可能是和原始的垃圾收集一样,等到内存消耗消灭极限时发生,这与

垃圾收集耦的选择和具体的设置都有关系。

(2)垃圾收集的准确性:主要包括2个方面:(a)垃圾收集器能够准确标记

活着的对象;(b)垃圾收集器能够准确地定位对象之间的引用关系。前者是完全

地回收全部废弃对象的前提,否则就可能造成内存泄漏。而后者则是实现归并和复

制等算法的必要条件。全部不行达对象都能够牢靠地得到回收,全部对象都能够重

安排,允许对象的复制和对象内存的缩并,这样就有效地防止内存的支离裂开。

(3)现在有很多种不同的垃圾收集器,每种有其算法且其表现各异,既有当

垃圾收集开头时就停顿应用程序的运行,又有当垃圾收集开头时也允许应用程序的

线程运行,还有在同一时间垃圾收集多线程运行。

(4)垃圾收集的实现和具体的JVM以及JVM的内存模型有格外严密的关系。

不同的JVM可能承受不同的垃圾收集,而JVM的内存模型打算着该JVM可以承

受哪些类型垃圾收集。现在,HotSpot系列JVM中的内存系统都承受先进的面对对

象的框架设计,这使得该系列JVM都可以承受最先进的垃圾收集。

(5)随着技术的进展,现代垃圾收集技术供给很多可选的垃圾收集器,而且

在配置每种收集器的时候乂可以设置不同的参数,这就使得依据不同的应用环境获

得最优的应用性能成为可能。

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论