本文目录一览

1,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的各域分配策略动态变化

jvm垃圾回收有哪些算法

2,JVM怎样确定一个对象是否可以被回收

比较常被提到的两种垃圾对象判定算法: 1.引用计数(reference counting) 概述:给对象添加一个引用计数器,每有一个地方引用这个对象,计数器值加1,每有一个引用失效则减1。 应用实例:python中使用了这种算法判定死对象。 优点:实现简单、...
比较常被提到的两种垃圾对象判定算法:1.引用计数(Reference Counting)概述:给对象添加一个引用计数器,每有一个地方引用这个对象,计数器值加1,每有一个引用失效则减1。应用实例:Python中使用了这种算法判定死对象。优点:实现简单、判定效率高缺点:难以解决对象之间的循环引用问题2.可达性分析(Reachability Analysis)概述:从GC Roots(每种具体实现对GC Roots有不同的定义)作为起点,向下搜索它们引用的对象,可以生成一棵引用树,树的节点视为可达对象,反之视为不可达。应用实例:Java,C#,Lisp都使用这种算法=====================================================================JVM使用“可达性分析算法”来判定一个对象是否会可以被回收,有两个细节需要注意:Java中GC Roots包括以下几种对象:a.虚拟机栈(帧栈中的本地变量表)中引用的对象b.方法区中静态属性引用的对象c.方法区中常量引用的对象d.本地方法栈中JNI引用的对象2.不可达对象一定会被回收吗不是。执行垃圾回收前JVM会执行不可达对象的finalize方法,如果执行完毕之后该对象变为可达,则不会被回收它。但一个对象的finalize方法只会被执行一次。参考资料:《深入理解Java虚拟机》周志明
1. 引用计数器算法解释系统给每个对象添加一个引用计数器,每当有一个地方引用这个对象的时候,计数器就加1,当引用失效的时候,计数器就减1,在任何一个时刻计数器为0的对象就是不可能被使用的对象,因为没有任何地方持有这个引用,这时这个对象就被视为内存垃圾,等待被虚拟机回收优点客观的说,引用计数器算法,他的实现很简单,判定的效率很高,在大部分情况下这都是相当不错的算法其实,很多案例中都使用了这种算法,比如 IOS 的Object-C , 微软的COM技术(用于给window开发驱动,.net里面的技术几乎都是建立在COM上的),Python语言等.缺陷无法解决循环引用的问题.这就好像是悬崖边的人采集草药的人, 想要活下去就必须要有一根绳子绑在悬崖上. 如果有两个人, 甲的手拉着悬崖, 乙的手拉着甲, 那么这两个人都能活, 但是, 如果甲的手拉着乙, 乙的手也拉着甲, 虽然这两个人都认为自己被别人拉着, 但是一样会掉下悬崖.比如说 A对象的一个属性引用B,B对象的一个属性同时引用A A.b = B() B.a = A(); 这个A,B对象的计数器都是1,可是,如果没有其他任何地方引用A,B对象的时候,A,B对象其实在系统中是无法发挥任何作用的,既然无法发挥作用,那就应该被视作内存垃圾予以清理掉,可是因为此时A,B的计数器的值都是1,虚拟机就无法回收A,B对象,这样就会造成内存浪费,这在计算机系统中是不可容忍的.解决办法在语言层面处理, 例如Object-C 就使用强弱引用类型来解决问题.强引用计数器加1 ,弱引用不增加Java中也有强弱引用2. 可达性分析算法解释这种算法通过一系列成为 "GC Roots " 的对象作为起始点,从这些节点开始向下搜索所有走过的路径成为引用链(Reference Chain) , 当一个对象GC Roots没有任何引用链相连(用图论的话来说就是从GC Roots到这个对象不可达),则证明此对象是不可用的优点这个算法可以轻松的解决循环引用的问题大部分的主流java虚拟机使用的都是这种算法3. Java语言中的GC Roots在虚拟机栈(其实是栈帧中的本地变量表)中引用的对象在方法区中的类静态属性引用对象在方法区中的常量引用的对象在本地方法栈中JNI(即一般说的Native方法)的引用对象

JVM怎样确定一个对象是否可以被回收

3,JAVA垃圾回收器如何工作

java回收器有gc以下是工作原理:强引用(StrongReference)这个就不多说,我们写代码天天在用的就是强引用。如果一个对象被被人拥有强引用,那么垃圾回收器绝不会回收它。当内存空间不足,Java 虚拟机宁愿抛出 OutOfMemoryError 错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。Java 的对象是位于 heap 中的,heap 中对象有强可及对象、软可及对象、弱可及对象、虚可及对象和不可到达对象。应用的强弱顺序是强、软、弱、和虚。对于对象是属于哪种可及的对象,由他的最强的引用决定。如下代码:String abc=new String("abc"); //1SoftReference<String> softRef=new SoftReference<String>(abc); //2WeakReference<String> weakRef = new WeakReference<String>(abc); //3abc=null; //4softRef.clear();//5第一行在 heap 堆中创建内容为“abc”的对象,并建立 abc 到该对象的强引用,该对象是强可及的。第二行和第三行分别建立对 heap 中对象的软引用和弱引用,此时 heap 中的 abc 对象已经有 3 个引用,显然此时 abc 对象仍是强可及的。第四行之后 heap 中对象不再是强可及的,变成软可及的。第五行执行之后变成弱可及的。软引用(SoftReference)如果一个对象只具有软引用,那么如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java 虚拟机就会把这个软引用加入到与之关联的引用队列中。软引用是主要用于内存敏感的高速缓存。在 jvm 报告内存不足之前会清除所有的软引用,这样以来 gc 就有可能收集软可及的对象,可能解决内存吃紧问题,避免内存溢出。什么时候会被收集取决于 gc 的算法和 gc 运行时可用内存的大小。当 gc 决定要收集软引用时执行以下过程,以上面的 softRef 为例:1 首先将 softRef 的 referent(abc)设置为 null,不再引用 heap 中的 new String("abc")对象。2 将 heap 中的 new String("abc")对象设置为可结束的(finalizable)。3 当 heap 中的 new String("abc")对象的 finalize()方法被运行而且该对象占用的内存被释放, softRef被添加到它的 ReferenceQueue(如果有的话)中。注意:对 ReferenceQueue 软引用和弱引用可以有可无,但是虚引用必须有。被 Soft Reference 指到的对象,即使没有任何 Direct Reference,也不会被清除。一直要到 JVM 内存不足且没有 Direct Reference 时才会清除,SoftReference 是用来设计 object-cache 之用的。如此一来SoftReference 不但可以把对象 cache 起来,也不会造成内存不足的错误 (OutOfMemoryError)。弱引用(WeakReference)如果一个对象只具有弱引用, 那该类就是可有可无的对象, 因为只要该对象被 gc 扫描到了随时都会把它干掉。弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程, 因此不一定会很快发现那些只具有弱引用的对象。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java 虚拟机就会把这个弱引用加入到与之关联的引用队列中。虚引用(PhantomReference)"虚引用"顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。程序如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。建立虚引用之后通过 get 方法返回结果始终为 null,通过源代码你会发现,虚引用通向会把引用的对象写进referent,只是 get 方法返回结果为 null。先看一下和 gc 交互的过程再说一下他的作用。1 不把 referent 设置为 null, 直接把 heap 中的 new String("abc")对象设置为可结束的(finalizable)。2 与软引用和弱引用不同, 先把 PhantomRefrence 对象添加到它的 ReferenceQueue 中.然后在释放虚可及的对象。

JAVA垃圾回收器如何工作

4,JVM如何判断哪些对象可以被回收

jvm要做垃圾回收时,首先要判断一个对象是否还有可能被使用。那么如何判断一个对象是否还有可能被用到?如果我们的程序无法再引用到该对象,那么这个对象就肯定可以被回收,这个状态称为不可达。当对象不可达,该对象就可以作为回收对象被垃圾回收器回收。那么这个可达还是不可达如何判断呢?答案就是GC roots ,也就是根对象,如果从一个对象没有到达根对象的路径,或者说从根对象开始无法引用到该对象,该对象就是不可达的。以下三类对象在jvm中作为GC roots,来判断一个对象是否可以被回收(通常来说我们只要知道虚拟机栈和静态引用就够了)虚拟机栈(JVM stack)中引用的对象(准确的说是虚拟机栈中的栈帧(frames))我们知道,每个方法执行的时候,jvm都会创建一个相应的栈帧(栈帧中包括操作数栈、局部变量表、运行时常量池的引用),栈帧中包含这在方法内部使用的所有对象的引用(当然还有其他的基本类型数据),当方法执行完后,该栈帧会从虚拟机栈中弹出,这样一来,临时创建的对象的引用也就不存在了,或者说没有任何gc roots指向这些临时对象,这些对象在下一次GC时便会被回收掉方法区中类静态属性引用的对象静态属性是该类型(class)的属性,不单独属于任何实例,因此该属性自然会作为gc roots。只要这个class存在,该引用指向的对象也会一直存在。class 也是会被回收的,在面后说明本地方法栈(Native Stack)引用的对象一个class要被回收准确的说应该是卸载,必须同时满足以下三个条件堆中不存在该类的任何实例加载该类的classloader已经被回收该类的java.lang.Class对象没有在任何地方被引用,也就是说无法通过反射再带访问该类的信息这篇内容太少了,在说几句java中的四种引用类型其实这四类引用的区别就在于GC时是否回收该对象强引用(Strong) 就是我们平时使用的方式 A a = new A();强引用的对象是不会被回收的软引用(Soft) 在jvm要内存溢出(OOM)时,会回收软引用的对象,释放更多内存弱引用(Weak) 在下次GC时,弱引用的对象是一定会被回收的虚引用(Phantom) 对对象的存在时间没有任何影响,也无法引用对象实力,唯一的作用就是在该对象被回收时收到一个系统通知
1. 引用计数器算法解释系统给每个对象添加一个引用计数器,每当有一个地方引用这个对象的时候,计数器就加1,当引用失效的时候,计数器就减1,在任何一个时刻计数器为0的对象就是不可能被使用的对象,因为没有任何地方持有这个引用,这时这个对象就被视为内存垃圾,等待被虚拟机回收优点客观的说,引用计数器算法,他的实现很简单,判定的效率很高,在大部分情况下这都是相当不错的算法其实,很多案例中都使用了这种算法,比如 IOS 的Object-C , 微软的COM技术(用于给window开发驱动,.net里面的技术几乎都是建立在COM上的),Python语言等.缺陷无法解决循环引用的问题.这就好像是悬崖边的人采集草药的人, 想要活下去就必须要有一根绳子绑在悬崖上. 如果有两个人, 甲的手拉着悬崖, 乙的手拉着甲, 那么这两个人都能活, 但是, 如果甲的手拉着乙, 乙的手也拉着甲, 虽然这两个人都认为自己被别人拉着, 但是一样会掉下悬崖.比如说 A对象的一个属性引用B,B对象的一个属性同时引用A A.b = B() B.a = A(); 这个A,B对象的计数器都是1,可是,如果没有其他任何地方引用A,B对象的时候,A,B对象其实在系统中是无法发挥任何作用的,既然无法发挥作用,那就应该被视作内存垃圾予以清理掉,可是因为此时A,B的计数器的值都是1,虚拟机就无法回收A,B对象,这样就会造成内存浪费,这在计算机系统中是不可容忍的.解决办法在语言层面处理, 例如Object-C 就使用强弱引用类型来解决问题.强引用计数器加1 ,弱引用不增加Java中也有强弱引用2. 可达性分析算法解释这种算法通过一系列成为 "GC Roots " 的对象作为起始点,从这些节点开始向下搜索所有走过的路径成为引用链(Reference Chain) , 当一个对象GC Roots没有任何引用链相连(用图论的话来说就是从GC Roots到这个对象不可达),则证明此对象是不可用的优点这个算法可以轻松的解决循环引用的问题大部分的主流java虚拟机使用的都是这种算法3. Java语言中的GC Roots在虚拟机栈(其实是栈帧中的本地变量表)中引用的对象在方法区中的类静态属性引用对象在方法区中的常量引用的对象在本地方法栈中JNI(即一般说的Native方法)的引用对象
比较常被提到的两种垃圾对象判定算法: 1.引用计数(reference counting) 概述:给对象添加一个引用计数器,每有一个地方引用这个对象,计数器值加1,每有一个引用失效则减1。 应用实例:python中使用了这种算法判定死对象。 优点:实现简单、...
比较常被提到的两种垃圾对象判定算法:1.引用计数(Reference Counting)概述:给对象添加一个引用计数器,每有一个地方引用这个对象,计数器值加1,每有一个引用失效则减1。应用实例:Python中使用了这种算法判定死对象。优点:实现简单、判定效率高缺点:难以解决对象之间的循环引用问题2.可达性分析(Reachability Analysis)概述:从GC Roots(每种具体实现对GC Roots有不同的定义)作为起点,向下搜索它们引用的对象,可以生成一棵引用树,树的节点视为可达对象,反之视为不可达。应用实例:Java,C#,Lisp都使用这种算法=====================================================================JVM使用“可达性分析算法”来判定一个对象是否会可以被回收,有两个细节需要注意:Java中GC Roots包括以下几种对象:a.虚拟机栈(帧栈中的本地变量表)中引用的对象b.方法区中静态属性引用的对象c.方法区中常量引用的对象d.本地方法栈中JNI引用的对象2.不可达对象一定会被回收吗不是。执行垃圾回收前JVM会执行不可达对象的finalize方法,如果执行完毕之后该对象变为可达,则不会被回收它。但一个对象的finalize方法只会被执行一次。

文章TAG:弱引用  引用  怎么  回收  弱引用jvm怎么回收  
下一篇