还剩8页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
j__a垃圾回收总结以前看过很多次关于垃圾回收相关的文章,都只是看过就忘记了,没有好好的整理一下,发现写文章可以强化自己的记忆 j__a与Cc++有很大的不同就是j__a语言__者不需要__内存信息,不会显式的直接操作内存,而是通过jvm虚拟机来实现j__a虚拟机运行的时候内存分配图如下图HYPERLINKhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204061525045558.jpgINCLUDEPICTUREhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204061525058034.jpg\*MERGEFORMAT jvm虚拟机栈一个是线程独有的,每次启动一个线程,就创建一个jvm虚拟机栈,线程退出的时候就销毁这里面主要保存线程本地变量名和局部变量值本地方法栈调用本地jni方法的时候而创建的这里分配的jvm之外的内存空间方法调用结束之后销毁pc寄存器这个保存线程当前执行的字节码指令堆主要保存创建的对象方法区保存class相关的信息主要是class的一个内存结构信息常量池方法区的一部分,主要保存class内存结构中常量值例如String值publicstaticfinal类型的值 我们这里说的垃圾回收,主要是j__a虚拟机对堆内存区域的回收 1首先的问题是jvm如何知道那些对象需要回收?目前有两种算法引用计数法每个对象上都有一个引用计数,对象每被引用一次,引用计数器就+1,对象引用被释放,引用计数器-1,直到对象的引用计数为0,对象就标识可以回收这个可以用数据算法中的图形表示,对象A-对象B-对象C都有引用,所以不会被回收,对象B由于没有被引用,没有路径可以达到对象B,对象B的引用计数就就是0,对象B就会被回收 HYPERLINKhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204061525059429.jpgINCLUDEPICTUREhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204061525051904.jpg\*MERGEFORMAT但是这个算法有明显的缺陷,对于循环引用的情况下,循环引用的对象就不会被回收例如下图对象A,对象B循环引用,没有其他的对象引用A和B,则A和B都不会被回收 HYPERLINKhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
20120406152505791.jpgINCLUDEPICTUREhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204061525055775.jpg\*MERGEFORMATroot搜索算法这种算法目前定义了几个root,也就是这几个对象是jvm虚拟机不会被回收的对象,所以这些对象引用的对象都是在使用中的对象,这些对象未使用的对象就是即将要被回收的对象简单就是说如果对象能够达到root,就不会被回收,如果对象不能够达到root,就会被回收如下图对象D访问不到根对象,所以就会被回收HYPERLINKhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204061525052395.jpgINCLUDEPICTUREhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204061525065426.jpg\*MERGEFORMAT以下对象会被认为是root对象被启动类(bootstrap加载器)加载的类和创建的对象jvm运行时方法区类静态变量static引用的对象jvm运行时方法去常量池引用的对象jvm当前运行线程中的虚拟机栈变量表引用的对象本地方法栈中jni引用的对象由于这种算法即使存在互相引用的对象,但如果这两个对象无法访问到根对象,还是会被回收如下图对象C和对象D互相引用,但是由于无法访问根,所以会被回收HYPERLINKhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204061525062362.jpgINCLUDEPICTUREhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
20120406152506377.jpg\*MERGEFORMATjvm在确定是否回收的对象的时候采用的是root搜索算法来实现在root搜索算法的里面,我们说的引用这里都指定的是强引用关系所谓强引用关系,就是通过用new方式创建的对象,并且显示关联的对象1O__ecto__=new O__ect;以上就是代表的是强引用关系,变量o__强引用了O__ect的一个对象j__a里面有四种应用关系,从强到弱分别为StrongReferen__(强引用–WeakReferen__弱引用)-SoftReferen__(软引用)–PhantomReferen__(引用) StrongReferen__只有在引用对象root不可达的情况下才会标识为可回收,垃圾回收才可能进行回收WeakReferen__即使在root算法中其引用的对象root可达到,但是如果jvm堆内存不够的时候,还是会被回收SoftReferen__无论其引用的对象是否root可达,在响应内存需要时,由垃圾回收判断是否需要回收PhantomReferen__在回收器确定其指示对象可另外回收之后,被加入垃圾回收队列. 下面可以看一个测试1234567891011121314151617181920212223242526272829public class Referen__Test{ public static final __pIntegerReferen____p=new Hash__pIntegerReferen__; public static void __inString[]args{ for int i=0;i1000;i++{ __p.putinew WeakReferen__new Referen__O__ecti; } int i=0; for Referen__r:__p.values{ if r.get==null{ i++; } } System.out.println被回收的对象数: +i; } static class Referen__O__ect{ private int i; private byte[]b; public Referen__O__ectint i{ this.i=i; b=new byte[1024 *10]; } }}这里创建大约1000个10K的WeakReferen__对象,最后打印的结果是被回收的对象数:767,这里Referen__O__ect如果设置为1K的话,最后的打印结果是0这个例子并不严谨,但是却说明了被WeakReferen__的对象在一定的时候会被jvm回收,但是强引用就不会出现这种状态j__a垃圾回收总结2上一篇文章 介绍了jvm虚拟机运行时内存结构以及如何标识需要回收的对象,这一节主要讲解垃圾回收的基本算法基本上jvm内存回收有三种基本算法标记-清除标记清除的算法最简单,主要是标记出来需要回收的对象,然后然后把这些对象在内存的信息清除如何标记需要回收的对象,在上一篇文章里面已经有说明HYPERLINKhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204131741425032.jpgINCLUDEPICTUREhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204131741421685.jpg\*MERGEFORMAT 标记-清除-压缩这个算法是在标记-清除的算法之上进行一下压缩空间,重新__对象的过程因为标记清除算__导致很多的留下来的内存空间碎片,随着碎片的增多,严重影响内存读写的性能,所以在标记-清除之后,会对内存的碎片进行整理最简单的整理就是把对象压缩到一边,留出另一边的空间由于压缩空间需要一定的时间,会影响垃圾收集的时间HYPERLINKhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204131741424749.jpgINCLUDEPICTUREhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204131741429766.jpg\*MERGEFORMAT 标记-清除-__这个算法是吧内存分配为两个空间,一个空间(A)用来负责装载正常的对象信息,另外一个内存空间(B)是垃圾回收用的每次把空间A中存活的对象全部__到空间B里面,在一次性的把空间A删除这个算法在效率上比标记-清除-压缩高,但是需要两块空间,对内存要求比较大,内存的利用率比较低适用于短生存期的对象,持续__长生存期的对象则导致效率降低HYPERLINKhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204131741429242.jpgINCLUDEPICTUREhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204131741432307.jpg\*MERGEFORMAT 由于现在的处理器都是多核的,处理器的性能得到了极大的提升,所以在此基础上有产生了几种垃圾收集算法主要包括两种算法并行标记清除所谓并行,就是原来垃圾回收只是一个线程进行现在创建多个垃圾回收线程并行的进行标记和清除比如把需要标记的对象平均分配到多个线程之后,当标记完成之后,多个线程进行清除 并发标记清除所谓并发,就是应用程序和垃圾回收可以同时执行在标记清除算法中,在标记对象和清除对象,以及压缩对象的情况下是需要暂停应用的那么并行标记清除压缩算法则是在标记清除压缩算法的基础上,把标记清除压缩算法分为以下几个过程初始标记-并发标记-重新标记-并发清除-重置 以上几种算法是垃圾回收的基本算法,jvm垃圾回收就是在以上几种算法为基础的,在以上几种算法的基础上,j__a垃圾回收器可以分为以下几种串行收集器用单线程处理所有垃圾回收工作,因为无需多线程交互,所以效率比较高但是,也无法使用多处理器的优势,所以此收集器适合单处理器机器单线程收集器在目前多核服务器端运行的情况下,效率比较低比较适合堆内存小的情况下使用HYPERLINKhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204131741439275.jpgINCLUDEPICTUREhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204131741436244.jpg\*MERGEFORMAT并行收集器用多线程处理所有垃圾回收工作,利用多核处理器的优势但是如果线程数量过多,导致线程之间频繁调度,也会影响性能一半并行收集的线程是处理器的个数“对吞吐量有高要求”,多CPU、对应用响应时间无要求的中、大型应用举例后台处理、科学计算HYPERLINKhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204131741433212.jpgINCLUDEPICTUREhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204131741438229.jpg\*MERGEFORMAT并发收集器并发收集器主要减少年老代的暂停时间,他在应用不停止的情况下使用__的垃圾回收线程,跟踪可达对象在每个年老代垃圾回收周期中,在收集初期并发收集器会对整个应用进行简短的暂停(初始标记的过程),在收集中还会再暂停一次第二次暂停会比第一次稍长(重新标记的过程),在此过程中多个线程同时进行垃圾回收工作并发收集器使用处理器换来短暂的停顿时间在一个N个处理器的系统上,并发收集部分使用K/N个可用处理器进行回收,一般情况下1=K=N/4在只有一个处理器的主机上使用并发收集器,设置为incrementalmode模式也可获得较短的停顿时间浮动垃圾由于在应用运行的同时进行垃圾回收,所以有些垃圾可能在垃圾回收进行完成时产生,这样就造成了“FloatingGarbage”,这些垃圾需要在下次垃圾回收周期时才能回收掉所以,并发收集器一般需要20%的预留空间用于这些浮动垃圾ConcurrentModeFailure并发收集器在应用运行时进行收集,所以需要保证堆在垃圾回收的这段时间有足够的空间供程序使用,否则,垃圾回收还未完成,堆空间先满了这种情况下将会发生“并发模式失败”,此时整个应用将会暂停,进行垃圾回收并发收集器,在垃圾回收的时候采用并发标记清除算法的收集器对响应时间要求高的,多CPU,大型应用比如页面请求/web服务器前端业务系统用的比较多我们以sun公司的hotspot虚拟机为例,hotspot采用的是分代回收算法,因为根据经验,一般80%的对象就是朝生夕灭,对象的生命期都很短而根据对象的生命周期不同,可以划分出来几个区域,一部分区域的对象创建比较频繁,但是生命周期比较短,一部分区域对象生命周期比较长,还有一部分区域对象生命周期几乎和j__a虚拟机相同sunspot堆内存分为三个区域HYPERLINKhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204131741449931.jpgINCLUDEPICTUREhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204131741449407.jpg\*MERGEFORMAT新生代(Young)新生代包括两个区Eden区和Survivor区,其中Survivor区一般也分成两块,简称Survivor1Spa__和Survivor2Spa__(或者FromSpa__和ToSpa__)新生代通常存活时间较短,因此基于标记清除__算法来进行回收,扫描出存活的对象,并__到一块新的完全未使用的空间中,对应于新生代,就是在Eden和From或To之间copy新生代采用空闲指针的方式来控制__触发,指针保持最后一个分配的对象在新生代区间的位置,当有新的对象要分配内存时,用于检查空间是否足够,不够就触发__当连续分配对象时,对象会逐渐从eden到Survior,最后到旧生代可以采用串行处理和并行处理器老年代(Old)在垃圾回收多次,如果对象仍然存活,并且新生代的空间不够,则对象会存放在老年代在老年代采用的是标记清除压缩算法因为老年代的对象一般存活时间比较长,每次标记清除之后,会有很多的零碎空间,这个就是所谓的浮动垃圾当老年代的零碎空间不足以分配一个大的对象的时候,就会采用压缩算法在压缩的时候,应用需要暂停可以采用串行处理,并行处理器,以及并发处理器持久代(Per__nent这部分空间主要存放j__a方法区的数据以及启动类加载器加载的对象这一部分对象通常不会被回收所以持久代空间在默认的情况下是不会被垃圾回收的 由于把内存空间分为三块,一般把新生代的__称为minor__,把老年代的__成为full__,所谓full__会先出发一次minor__,然后在进行老年代的__具体的过程如下首先想eden区申请分配空间,如果空间够,就直接进行分配,否则进行一次Minor__minor__首先会对Eden区的对象进行标记,标记出来存活的对象然后把存活的对象copy到From空间如果From空间足够,则回收eden区可回收的对象如果from内存空间不够,则把From空间存活的对象__到To区,如果TO区的内存空间也不够的话,则把To区存活的对象__到老年代如果老年代空间也不够(或者达到触发老年年垃圾回收条件的话)则触发一次full__简单方向就是Eden-From-To-Old,如下图所示HYPERLINKhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
201204131741446932.jpgINCLUDEPICTUREhttp://images.cnblogs.com/cnblogs_com/aigongsi/201204/
20120413174144869.jpg\*MERGEFORMAT。