本文目录一览

1,Java的GC机制到底怎么回事

这个有点复杂,现在JVM应该都是分代回收,具体你可以去看一下JVM原理;简单点说就是: 你 new 出来的对象,当不用的时候是不会马上回收的;JVM分时间,分阶段逐步回收;当然,如果你直接调用System.gc()的话;这时候会引发 full gc();也就是JVM里面不被引用的对象都会被回收一次,资源消耗的代价是比较高的;你可以用jstat命令查看到具体的回收过程,回收次数等信息
程序员是无法让system.gc();按照规则调用的,你可以在程序启动过程中写上这段代码,不过至于什么时候调用就要看jvm了.不过,觉得你的程序或许应该有地方资源泄漏了吧,假如你的机器是2g内存,一般运行windowsxp,大概也就用1/4内存,再加上的jvm,1g应该搞定了,剩下的1g,你用来加载信息,个人觉得,如果启动就死是不太可能的,如果运行一段时间,程序写的不完善可能会死掉,个人建议你还是好好看看自己的程序吧,如果确认程序没问题,那就只有加内存了,没有别的办法,光靠jvm的垃圾回收,效果不是很多.

Java的GC机制到底怎么回事

2,垃圾回收的优点和原理

Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收
java垃圾回收的优点:它使得java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。 java垃圾回收的原理: 垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。

垃圾回收的优点和原理

3,java的gc能立即回收垃圾吗

用finalize方法跟gc可以去回收,但是具有不确定性.如果你要回收的对象里面还有线程在运行,调用system.gc没用,也不会调用你的finalize方法.
不一定。现在jvm采用分代回收机制,简单来说就是分为新生代和老生代,老生代内存空间比新生代大;大部分新对象都会优先分配到新生代,当新生代空间满了会发起一次Minor GC。而新分配的大对象或者在新生代空间里存活很久的对象会被放到老生代里,老生代空间满了会发起Major GC,但由于老生代里的对象生命周期比较长加上Major GC速度比Minor GC慢很多,所以发生在老生代的Major GC相对会比Minor GC少很多。因此垃圾能不能被立即回收,要看垃圾的大小,它所处在的空间和当前所处空间是否已满才能基本确定。若想了解得更详细,可以看看《深入理解Java虚拟机:JVM高级特性与最佳实践》这本书。
垃圾回收的缩写就是gc。无论java还是c#的gc都是相应的虚拟机用来释放无用内存的机制,不同之处在于他们用的虚拟机不同。c++的析构函数是程序员手动写的回收内存和善后处理的函数。其功能相当与java的gc(回收内存)和finallize(善后处理)方法加起来。

java的gc能立即回收垃圾吗

4,主流的垃圾回收机制都有哪些

跟踪回收  跟踪回收的方式独立于程序,定期运行来检查垃圾,需要较长时间的中断。  标记清除  标记清除的方式需要对程序的对象进行两次扫描,第一次从根(Root)开始扫描,被根引用了的对象标记为不是垃圾,不是垃圾的对象引用的对象同样标记为不是垃圾,以此递归。所有不是垃圾的对象的引用都扫描完了之后。就进行第二次扫描,第一次扫描中没有得到标记的对象就是垃圾了,对此进行回收。  复制收集  复制收集的方式只需要对对象进行一次扫描。准备一个「新的空间」,从根开始,对对象进行扫,如果存在对这个对象的引用,就把它复制到「新空间中」。一次扫描结束之后,所有存在于「新空间」的对象就是所有的非垃圾对象。
java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。

5,jvm垃圾回收有哪些算法

1.堆的分代和区域 (年轻代)Young Generation(eden、s0、s1 space) Minor GC (老年代)Old Generation (Tenured space) Major GC|| Full GC (永久代)Permanent Generation (Permanent space)【方法区(method area)】 Major GC 本地化的String从JDK 7开始就被移除了永久代(Permanent Generation ) JDK 8.HotSpot JVM开始使用本地化的内存存放类的元数据,这个空间叫做元空间(Metaspace)2.判断对象是否存活(哪些是垃圾对象) 1.引用计数(ReferenceCounting):对象有引用计数属性,增加一个引用计数加1,减少一个引用计数减1,计数为0时可回收。(无法解决对象相互循环引用的问题) 2.根搜索(GC Roots Tracing):GCRoot对象作为起始点(根)。如果从根到某个对象是可达的,则该对象称为“可达对象”(存活对象,不可回收对象)。否则就是不可达对象,可以被回收。 下图中,对象Object6、Object7、Object8虽然互相引用,但他们的GC Roots是不可到达的,所以它们将会被判定为是可回收的对象3.垃圾收集算法 1.标记-清除(Mark-Sweep)算法: 标记清除算法分为“标记”和“清除”两个阶段:首先标记出需要回收的对象,标记完成之后统一清除对象。 缺点: 1、标记和清除效率不高; 2、产生大量不连续的内存碎片,导致有大量内存剩余的情况下,由于,没有连续的空间来存放较大的对象,从而触发了另一次垃圾收集动作。2.复制(Copying)算法: 将可用内存容量划分为大小相等的两块,每次只使用其中的一块。当这一块用完之后,就将还存活的对象复制到另外一块上面,然后在把已使用过的内存空间一次清理掉。这样使得每次都是对其中的一块进行内存回收
1.垃圾回收目的:java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,java中的对象不再有“作用域”的概念,只有对象的引用才有“作用域”。垃圾回收可以有效的防止内存泄露,有效的使用空闲的内存。ps:内存泄露是指该内存空间使用完毕之后未回收,在不涉及复杂数据结构的一般情况下,java 的内存泄露表现为一个内存对象的生命周期超出了程序需要它的时间长度,我们有时也将其称为“对象游离”。2.由于对象进行了分代处理,因此垃圾回收区域、时间也不一样。gc有两种类型:scavenge gc和full gc。scavenge gc一般情况下,当新对象生成,并且在eden申请空间失败时,就会触发scavenge gc,对eden区域进行gc,清除非存活对象,并且把尚且存活的对象移动到survivor区。然后整理survivor的两个区。这种方式的gc是对年轻代的eden区进行,不会影响到年老代。因为大部分对象都是从eden区开始的,同时eden区不会分配的很大,所以eden区的gc会频繁进行。因而,一般在这里需要使用速度快、效率高的算法,使eden去能尽快空闲出来。full gc对整个堆进行整理,包括young、tenured和perm。full gc因为需要对整个堆进行回收,所以比scavenge gc要慢,因此应该尽可能减少full gc的次数。在对jvm调优的过程中,很大一部分工作就是对于fullgc的调节。有如下原因可能导致full gc:1.年老代(tenured)被写满2.持久代(perm)被写满3.system.gc()被显示调用4.上一次gc之后heap的各域分配策略动态变化

6,JVM有哪些垃圾回收算法

1.Mark-Sweep(标记-清除)算法这是最基础的垃圾回收算法,之所以说它是最基础的是因为它最容易实现,思想也是最简单的。标记-清除算法分为两个阶段:标记阶段和清除阶段。标记阶段的任务是标记出所有需要被回收的对象,清除阶段就是回收被标记的对象所占用的空间。2.Copying(复制)算法  为了解决Mark-Sweep算法的缺陷,Copying算法就被提了出来。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用的内存空间一次清理掉,这样一来就不容易出现内存碎片的问题。3.Mark-Compact(标记-整理)算法(压缩法)为了解决Copying算法的缺陷,充分利用内存空间,提出了Mark-Compact算法。该算法标记阶段和Mark-Sweep一样,但是在完成标记之后,它不是直接清理可回收对象,而是将存活对象都向一端移动,然后清理掉端边界以外的内存。4.Generational Collection(分代收集)算法分代收集算法是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根据对象存活的生命周期将内存划分为若干个不同的区域。一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。
1.标记清除标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。在标记阶段首先通过根节点(GC Roots),标记所有从根节点开始的对象,未被标记的对象就是未被引用的垃圾对象。然后,在清除阶段,清除所有未被标记的对象。适用场合:存活对象较多的情况下比较高效适用于年老代(即旧生代)缺点:容易产生内存碎片,再来一个比较大的对象时(典型情况:该对象的大小大于空闲表中的每一块儿大小但是小于其中两块儿的和),会提前触发垃圾回收扫描了整个空间两次(第一次:标记存活对象;第二次:清除没有标记的对象)2.复制算法从根集合节点进行扫描,标记出所有的存活对象,并将这些存活的对象复制到一块儿新的内存(图中下边的那一块儿内存)上去,之后将原来的那一块儿内存(图中上边的那一块儿内存)全部回收掉请点击输入图片描述现在的商业虚拟机都采用这种收集算法来回收新生代。适用场合:存活对象较少的情况下比较高效扫描了整个空间一次(标记存活对象并复制移动)适用于年轻代(即新生代):基本上98%的对象是"朝生夕死"的,存活下来的会很少缺点:需要一块儿空的内存空间需要复制移动对象3.标记整理复制算法的高效性是建立在存活对象少、垃圾对象多的前提下的。这种情况在新生代经常发生,但是在老年代更常见的情况是大部分对象都是存活对象。如果依然使用复制算法,由于存活的对象较多,复制的成本也将很高。请点击输入图片描述标记-压缩算法是一种老年代的回收算法,它在标记-清除算法的基础上做了一些优化。首先也需要从根节点开始对所有可达对象做一次标记,但之后,它并不简单地清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后,清理边界外所有的空间。这种方法既避免了碎片的产生,又不需要两块相同的内存空间,因此,其性价比比较高。4.分代收集算法分代收集算法就是目前虚拟机使用的回收算法,它解决了标记整理不适用于老年代的问题,将内存分为各个年代。一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),在堆区之外还有一个代就是永久代(Permanet Generation)。在不同年代使用不同的算法,从而使用最合适的算法,新生代存活率低,可以使用复制算法。而老年代对象存活率搞,没有额外空间对它进行分配担保,所以只能使用标记清除或者标记整理算法。请点击输入图片描述垃圾回收机制根据直通BAT必考题系列:深入详解JVM内存模型与JVM参数详细配置所说,年轻代分为Eden区和survivor区(两块儿:from和to),且Eden:from:to==8:1:1。请点击输入图片描述jvm内存结构1)新产生的对象优先分配在Eden区(除非配置了-XX:PretenureSizeThreshold,大于该值的对象会直接进入年老代);2)当Eden区满了或放不下了,这时候其中存活的对象会复制到from区。这里,需要注意的是,如果存活下来的对象from区都放不下,则这些存活下来的对象全部进入年老代。之后Eden区的内存全部回收掉。3)之后产生的对象继续分配在Eden区,当Eden区又满了或放不下了,这时候将会把Eden区和from区存活下来的对象复制到to区(同理,如果存活下来的对象to区都放不下,则这些存活下来的对象全部进入年老代),之后回收掉Eden区和from区的所有内存。4)如上这样,会有很多对象会被复制很多次(每复制一次,对象的年龄就+1),默认情况下,当对象被复制了15次(这个次数可以通过:-XX:MaxTenuringThreshold来配置),就会进入年老代了。5)当年老代满了或者存放不下将要进入年老代的存活对象的时候,就会发生一次Full GC(这个是我们最需要减少的,因为耗时很严重)。垃圾回收有两种类型:Minor GC 和 Full GC。1.Minor GC对新生代进行回收,不会影响到年老代。因为新生代的 Java 对象大多死亡频繁,所以 Minor GC 非常频繁,一般在这里使用速度快、效率高的算法,使垃圾回收能尽快完成。2.Full GC也叫 Major GC,对整个堆进行回收,包括新生代和老年代。由于Full GC需要对整个堆进行回收,所以比Minor GC要慢,因此应该尽可能减少Full GC的次数,导致Full GC的原因包括:老年代被写满、永久代(Perm)被写满和System.gc()被显式调用等。垃圾回收算法总结1.年轻代:复制算法1) 所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。2) 新生代内存按照8:1:1的比例分为一个eden区和两个survivor(survivor0,survivor1)区。一个Eden区,两个 Survivor区(一般而言)。大部分对象在Eden区中生成。回收时先将eden区存活对象复制到一个survivor0区,然后清空eden区,当这个survivor0区也存放满了时,则将eden区和survivor0区存活对象复制到另一个survivor1区,然后清空eden和这个survivor0区,此时survivor0区是空的,然后将survivor0区和survivor1区交换,即保持survivor1区为空, 如此往复。3) 当survivor1区不足以存放 eden和survivor0的存活对象时,就将存活对象直接存放到老年代。若是老年代也满了就会触发一次Full GC(Major GC),也就是新生代、老年代都进行回收。4) 新生代发生的GC也叫做Minor GC,MinorGC发生频率比较高(不一定等Eden区满了才触发)。2.年老代:标记-清除或标记-整理1) 在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。2) 内存比新生代也大很多(大概比例是1:2),当老年代内存满时触发Major GC即Full GC,Full GC发生频率比较低,老年代对象存活时间比较长,存活率标记高。以上这种年轻代与年老代分别采用不同回收算法的方式称为"分代收集算法",这也是当下企业使用的一种方式3. 每一种算法都会有很多不同的垃圾回收器去实现,在实际使用中,根据自己的业务特点做出选择就好。
常用的垃圾回收算法有: (1).引用计数算法: 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器都为0的对象就是不再被使用的,垃圾收集器将回收该对象使用的内存。 引用计数算法实现简单,效率很高,微软的com技术、actionscript、python等都使用了引用计数算法进行内存管理,但是引用计数算法对于对象之间相互循环引用问题难以解决,因此java并没有使用引用计数算法。 (2).根搜索算法: 通过一系列的名为“gc root”的对象作为起点,从这些节点向下搜索,搜索所走过的路径称为引用链(reference chain),当一个对象到gc root没有任何引用链相连时,则该对象不可达,该对象是不可使用的,垃圾收集器将回收其所占的内存。 主流的商用程序语言c#、java和lisp都使用根搜素算法进行内存管理。 在java语言中,可作为gc root的对象包括以下几种对象: a. java虚拟机栈(栈帧中的本地变量表)中的引用的对象。 b.方法区中的类静态属性引用的对象。 c.方法区中的常量引用的对象。 d.本地方法栈中jni本地方法的引用对象。 java方法区在sun hotspot虚拟机中被称为永久代,很多人认为该部分的内存是不用回收的,java虚拟机规范也没有对该部分内存的垃圾收集做规定,但是方法区中的废弃常量和无用的类还是需要回收以保证永久代不会发生内存溢出。 判断废弃常量的方法:如果常量池中的某个常量没有被任何引用所引用,则该常量是废弃常量。 判断无用的类: (1).该类的所有实例都已经被回收,即java堆中不存在该类的实例对象。 (2).加载该类的类加载器已经被回收。 (3).该类所对应的java.lang.class对象没有任何地方被引用,无法在任何地方通过反射机制访问该类的方法。 java中常用的垃圾收集算法: (1).标记-清除算法: 最基础的垃圾收集算法,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成之后统一回收掉所有被标记的对象。 标记-清除算法的缺点有两个:首先,效率问题,标记和清除效率都不高。其次,标记清除之后会产生大量的不连续的内存碎片,空间碎片太多会导致当程序需要为较大对象分配内存时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。 (2).复制算法: 将可用内存按容量分成大小相等的两块,每次只使用其中一块,当这块内存使用完了,就将还存活的对象复制到另一块内存上去,然后把使用过的内存空间一次清理掉。这样使得每次都是对其中一块内存进行回收,内存分配时不用考虑内存碎片等复杂情况,只需要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。 复制算法的缺点显而易见,可使用的内存降为原来一半。 (3).标记-整理算法: 标记-整理算法在标记-清除算法基础上做了改进,标记阶段是相同的标记出所有需要回收的对象,在标记完成之后不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,在移动过程中清理掉可回收的对象,这个过程叫做整理。 标记-整理算法相比标记-清除算法的优点是内存被整理以后不会产生大量不连续内存碎片问题。 复制算法在对象存活率高的情况下就要执行较多的复制操作,效率将会变低,而在对象存活率高的情况下使用标记-整理算法效率会大大提高。 (4).分代收集算法: 根据内存中对象的存活周期不同,将内存划分为几块,java的虚拟机中一般把内存划分为新生代和年老代,当新创建对象时一般在新生代中分配内存空间,当新生代垃圾收集器回收几次之后仍然存活的对象会被移动到年老代内存中,当大对象在新生代中无法找到足够的连续内存时也直接在年老代中创建。

文章TAG:回收  java  机制  到底  分代回收  
下一篇