g1使用什么垃圾收集算法,垃圾收集算法效率比较
目录
1垃圾回收三件事:哪些内存需要回收:何时如何回收死对象。根据jvm内存区域划分的原理:程序计数器、虚拟机栈、本地方法栈的内存是随着线程的创建而划分的,所以当线程结束时,内存自动释放。
本章分析了Java堆和方法区的内存管理策略。
1.虚拟机堆栈,本地方法堆栈。堆栈中的堆栈帧随着方法的进入和退出以有序的方式执行弹出和进入堆栈的操作。
每个栈帧分配多少内存在类结构确定的时候就基本知道了(虽然在运行时会被即时编译器优化,但在基于概念模型的讨论中一般可以认为是编译时已知的),所以这些区域的内存分配和回收是确定性的。
2.在堆和方法领域存在显著的不确定性:一个接口的多个实现类所需的内存可能不同,一个方法执行的不同条件分支所需的内存也可能不同。
只有在运行的时候才能知道程序会创建哪些对象,创建多少对象,这部分内存的分配和回收是动态的。2对象存活判定算法回收堆,即回收对象。判断对象是否需要回收,即对象是否死的策略有两种:引用计数算法和可达性分析算法。
2.1引用计数算法给对象增加一个引用计数器,每有一个对它的引用,计数器值就加1;当引用无效时,计数器值减1;任何时间计数器为零的对象都不能再使用。
缺点:当对象有相互引用时,这种判断方法失效。目前很少有java虚拟机应用该算法对引用进行分类。
定义
垃圾回收
有力的引用
引用赋值在程序中无处不在。
不回收
软引用
一些有用但不必要的对象。软参考装饰
只有快要溢出的时候才会回收。
弱引用
实力比软报价弱一点。弱引用修改
当垃圾收集器启动时,它将被收集,不管是否溢出。
虚拟参考
目的是在收集器收集该对象时接收系统通知。
当垃圾收集器启动时,它将被回收[设置虚拟引用的目的只是为了在对象被回收时收到通知]
2.2可达性分析算法根据引用关系向下遍历GC根节点。当现有对象不在引用连接中时,它可能不会被引用。
注意:目前选举根节点时,仍然需要暂停所有用户线程,以保证快照的一致性。
在Java技术系统中,可以用作GC根的固定对象包括:
虚拟机栈中引用的对象,比如每个线程使用的方法栈中的类静态属性引用的参数、局部变量、临时变量等对象,比如Java类的引用类型,静态变量方法区中的常量引用的对象,比如字符串常量池中的引用引用本地方法栈中的原生方法引用的对象。同步锁持有的所有对象2.2.1不可达对象的后处理。在对象被判断为不可达之后,它仍然可能不被回收:finalize()方法被调用,其他幸存的对象在方法中被调用。
所以,不可达对象第一次被标记后,会有一个执行判断过程:
当对象被判断为不可达时,第一次被标记。筛选出被标记的对象,确定finalize()方法是否需要执行,必要时放入执行队列。在finalize()中,如果生成了对活对象的引用,jvm将从回收的集合中删除不可到达的对象。流程如下:
关于finalize()方法,它的操作开销大,不确定,而且不能保证每个对象的调用顺序。所以不建议所有能做的工作都用finalize(),可以用try-finally或者其他方法做的更好。2.3方法区回收判断方法区回收条件苛刻,成本高。055-79000不需要在方法区域进行垃圾收集。热点虚拟机中的元空间或永久生成是方法区的垃圾收集,没有垃圾收集行为。垃圾回收主要包括两部分:丢弃的常量和未使用的类型。1.确定常量是否被丢弃。常量池中没有对象引用该常量,虚拟机中也没有其他地方引用该常量。2.确定该类型是否不再使用。该类的所有实例都已被回收,也就是说,在Java堆中没有该类及其任何派生子类的实例。加载该类的类加载器已被回收。该类对应的java.lang.Class对象在任何地方都没有被引用,不可能通过反射在任何地方访问该类。允许Java虚拟机回收满足以上三个条件的无用类。这里说的只是“允许”,并不等同于对象。如果不被引用,将被回收。
至于是否回收类型,HotSpot虚拟机提供了-Xnoclassgc参数来控制,也可以使用-verbose: class和-xx: traceclass-loading,-xx: traceclassunloading来查看类加载和卸载的信息。5垃圾收集算法介绍。5.1代集论!重要信息将堆内存划分为多个区域并存储不同年龄的对象是非常重要的。(即分为新生代和老一代);新生代对象可以转移到老年;对于新一代人来说,只有少量需要保留的物品在回收中受到关注;对于老年,使用低频进行回收;由于分区的出现,可以在特定的区域进行回收,也可以在不同的区域使用不同的回收算法。对于跨代对象,在新生代建立一个内存表,存储旧时代哪些区域有跨带引用,回收时只处理这个区域的对象;关于托收的补充说明
部分GC:指垃圾收集,其目标不是完全收集整个Java堆。它分为:
Major GC/Old GC:指目标只是旧时代的垃圾收集。混合GC:指整个新一代和部分老一代的垃圾收集。Full GC:整个Java堆和方法区域的垃圾收集。5.1.1内存集和卡表内存集的用途:解决跨带引用造成的扫描整个老年的问题。它是存储在非收集区的指针集的数据结构,元素指向收集区的卡片表:内存集精确到内存区,称为卡片表;抽象为字节数组卡页:卡表的一个元素:内存块:存储一个内存地址,按照指定页号的大小(2的n次方字节数)形成地址范围;卡片页的存储器通常包含多个对象。只要卡片页中一个(或多个)对象的字段中存在跨代指针,对应卡片表的数组元素的值就标识为1,称为脏;否则,它被标识为0。当垃圾收集发生时,只要筛选出卡表中的脏元素,就很容易找出哪些卡页内存块包含了跨代指针,并将其添加到GC根中一起扫描。5.2标记-清除算法标记所有要回收的对象,以清除标记的对象。缺点:1。如果有大量的对象需要清除,那么标记-清除操作就比较多(我的理解是既然清除了,就不需要标记);2.产生记忆碎片。5.3 Flag-Copy算法将内存平均分成两个区域,所有新对象放在一个区域A;当这个区域的内存用完时,将活体复制到另一个区域b;一半以上的面积已经用于回收和清理;同时,新的对象只会出现在B区;优点:不会产生内存碎片(存活的对象放在一起,要回收的对象整体清除)。缺点:1。复制会产生开销;2.内存浪费:只剩下一半的可用内存。5.4优化后的logo-copy算法把新一代分为三个区域:一个是伊甸园,一个是幸存者。分别占据10:8 10:1 10:1,新生成的对象随机进入伊甸园和现有的幸存者之一。当垃圾收集发生时,将Eden和Survivor中幸存的对象一次性复制到另一个Survivor空间,然后直接清理Eden和使用过的Survivor。当Survivor不足以存储幸存对象时,移至old age。如果对象在18GC后仍然存活,也会转移到老年,如图:
5.5打标-整理算法打标过程仍与“打标-清除”算法相同;可回收对象不是直接回收,而是将所有存活的对象都移到内存空间的一端,然后直接清理边界外的内存。缺点:对象被移动,需要更新其引用,需要停止所有正在运行的线程进程,如图:
6根节点枚举6.1关于根节点及其枚举的数据可以作为根节点集中在:方法区【数量池,静态变量】,虚拟机栈:【局部变量表】根节点枚举,用户线程需要挂起。此外,查找引用链的过程已经实现为与用户线程并发。6.2什么是oopMap数据结构?OopMap是一种数据结构,它存储的内容可以作为根节点。当jvm执行一些字节码指令时,它将创建这个数据结构。为什么需要oopMap?优点:使用oopMap,jvm可以直接找到对象的引用,不需要检查所有的执行上下文和全局引用位置,不会遗漏,从而快速完成根节点枚举。缺点:导致OopMap内容变化的指令很多,如果为每条指令生成相应的oopMap,将需要大量额外的存储空间。如何实现oopMap:类加载后,保存对象的属性的偏移地址。【注1】即时编译时,保存对象在栈中的引用地址【注2】[]注1:属性的偏移量应该在对象创建后才确定,类加载后无法确定对象信息。澄清todo[]注2:类似地,对象的创建发生在运行时。编译时如何获取引用的地址?下面关于实时编译的章节会解释todo6.3的安全点是什么?当编译字节码指令时,oopMap只为特定的指令创建。我们称这些特定指令的地址为安全点。为什么需要安全?如果对所有指令都生成oopMap,会消耗大量空间;选择一个安全点创建oopMap,这样可以节省内存空间。有了安全点的设置,也就决定了用户程序执行时,不能停在代码指令流中的任何位置开始垃圾回收,但强制要求执行必须到达安全点才能暂停。如何实现安全?安全点的位置选择在有允许程序长时间执行的可重用指令时,如方法调用、循环跳转、异常跳转等。只有具有这些功能的指令才会产生安全点。JVM主动中断方案用于暂停线程的执行,以响应GC事件。关于主动中断当垃圾收集需要中断一个线程时,并不直接挂起线程,只是设置一个标志位。每个线程在执行时都会轮询这个标志,一旦发现中断标志为真,就会主动中断,在最近的安全点挂起自己;另一种方案是抢先中断:[主流虚拟机不使用这种方案]
抢先中断不需要线程的执行代码主动配合。当垃圾收集发生时,系统首先中断所有用户线程。如果发现一个用户线程被中断的地方不在安全点,它会恢复这个线程的执行,稍后让它再次中断,直到到达安全点。6.4什么是安全区?在这个代码片中,对象引用关系不会改变,所以这个代码(或者字节码指令片段)是一个安全区域。为什么你需要一个安全的地方?当线程不分配cpu时间(处于睡眠或阻塞状态)时,无法响应虚拟机的中断请求。如果它不能去安全的地方打断自己上吊,安全点的设置就失效了,所以它需要一个安全的区域。在安全的地方收集垃圾是安全的。安全性对线程和回收器的影响:当用户线程在安全区域执行代码时,它首先会识别自己已经进入了安全区域。当虚拟机开始垃圾回收时,不会用暂停标志(对应主动中断的标记)标记安全区的线程。当线程离开安全区时,会检查虚拟机是否已经枚举完根节点:完成:线程会被当作什么都没发生,继续执行未完成:线程会一直等到收到可以离开安全区的信号。用一张图来形容:
6.5 OOP图的对比和总结,安全点和安全区域用一张图总结:
版权归作者所有:原创作品来自博主小二上九8,转载请联系作者取得转载授权,否则将追究法律责任。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。