垃圾回收器的原则

  使用过C++的人应该知道,使用new运算符在堆上创建对象的代价是非常高的——不但创建很麻烦,管理也很麻烦。Java也是通过new运算符在堆上创建对象,但是很明显有着较高的速度。这就要归功于垃圾回收器的存在了。

C++的堆分配和Java堆分配的不同之处

  C++堆的管理是由程序员来负责的,这就意味着,对于一块分配出去的堆内存回收的时候可能已经碎片化了(有的回收,有的还在用),当再次申请空间时,以前空出来的可能不足以存放新创建的对象,这就使得在程序运行过程中内存块会出现这样的“空穴”,造成不必要的内存浪费。但是这种情况在Java中得到好转——首先,垃圾回收器会通过回收算法对内存空间进行回收和整理,使得堆内存局部保持紧凑并回收部分对象内存(因为编程问题)。

垃圾回收器的“自适应”技术

  可能更多的人认识“自适应”这个词是在硬件层次上,如:CPU、显卡的驱动上。但是在Java中,它也有所体现。”自适应“主要体现在对算法的动态选择上。垃圾回收器有两种基础的算法:“停止-复制”和“标记-清扫”,和一种几乎不曾实现的算法:“引用计数法”。

引用计数法

  引用计数法,就是通过引用的数量对对象是否存活进行判断。当所有的引用都不存在时,即引用数为0时,即可回收。但是,对于已经失去类似遍历引用的数据结构,如:双向链表,除了节点间的互相引用,已经没有遍历引用作用在上面,这样的链表已经不可能找到了。但是引用数不为0,又不能释放。所以,这个算法是种思想,但不是很实用。

停止-复制

  暂停虚拟机中的程序,通过活对象进行向上查找,一直追溯到存活在堆栈或静态数据区中的引用,以此形成“活对象森林”,将这些对象重定向到新的堆上,剩下没遍历到的就是该回收的。新的堆上的对象排列紧密,从而进一步节省空间。当然,对象的引用也要随之修正。这种情况适用于回收对象较多,产生内存碎片较多时,全面的整理。

标记-清扫

  同样是暂停虚拟机中的应用,只不过“停止-复制”是从下向上,追本溯源;而“标记-清扫”是由上而下,从祖到子。由堆栈或静态数据区出发,一道查找活的对象,并将其标记,等完成后,没标记的就是该回收的。注意,这里会收完后并不对堆进行紧凑优化,所以更适合于垃圾较少,碎片较少的情况。

  这样,虚拟机在进行垃圾清理时,就会根据垃圾回收器的回收效率判断该使用哪种回收方式,显然这是“自适应”的体现。

原文地址:https://www.cnblogs.com/fusiji/p/11409880.html

时间: 2024-11-14 13:24:20

垃圾回收器的原则的相关文章

[Think In Java]基础拾遗1 - 对象初始化、垃圾回收器、继承、组合、代理、接口、抽象类

目录 第一章 对象导论第二章 一切都是对象第三章 操作符第四章 控制执行流程第五章 初始化与清理第六章 访问权限控制第七章 复用类第九章 接口 第一章 对象导论 1. 对象的数据位于何处? 有两种方式在内存中存放对象: (1)为了追求最大的执行速度,对象的存储空间和生命周期可以在编写程序时确定,这可以通过将对象置于堆栈或者静态存储区域内来实现.这种方式牺牲了灵活性. (2)在被称为堆的内存池中动态地创建对象.在这种方式,知道运行时才知道对象需要多少对象,它们的生命周期如何,以及它们的具体类型.

深入理解JVM虚拟机3:垃圾回收器详解

JVM GC基本原理与GC算法 微信公众号[Java技术江湖]一位阿里 Java 工程师的技术小站.作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux.网络.多线程,偶尔讲点Docker.ELK,同时也分享技术干货和学习经验,致力于Java全栈开发!(关注公众号后回复”Java“即可领取 Java基础.进阶.项目和架构师等免费学习资料,更有数据库.分布式.微服务等热门技术学习视频,内容丰富,兼顾原理和实践,另外也将赠送作者原创的Jav

了解CMS(Concurrent Mark-Sweep)垃圾回收器

http://www.iteye.com/topic/1119491 1.总体介绍: CMS(Concurrent Mark-Sweep)是以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器.对于要求服务器响应速度的应用上,这种垃圾回收器非常适合.在启动JVM参数加上-XX:+UseConcMarkSweepGC ,这个参数表示对于老年代的回收采用CMS.CMS采用的基础算法是:标记-清除. 2.CMS过程: 初始标记(STW initial mark) 并发标记(Concurrent mar

总结Java垃圾回收器的方法和原理

1. 垃圾回收只与内存有关 在Java中,我们new完对象之后,垃圾回收器负责回收无用的对象占据的内存资源.这与C++不同,在C++中,准许使用局部对象,回收对象时候,需要用到finalize()析构函数.C++的对象创建在堆栈中,而Java对象创建在堆中,所以我们创建完对象之后,Java的垃圾回收器在堆中,会自动帮我们回收垃圾,至于何时回收垃圾,我们不得而知了. 2.垃圾回收用到的方法 (1)finalize() 该方法是用来回收“特殊”的内存,而这内存不是new出来的,所以垃圾回收器无法回收

垃圾回收器设计

1利用栈对象自动释放(可以禁止析构函数就不能产生栈对象了哦 小技巧) 利用栈对象出作用域自动释放的特性构造一个空的智能指针类 2解决智能释放问题,只要这样就不用手工delete类指针了 在智能指针类的析构函数里面delete对象成员去对象里面释放垃圾指针等.. 3解决被智能指针代理的真实对象的函数的调用问题 重载->运算符,以便能直接调用这个智能指针存储的对象中的函数 或者使用代理模式不过没有重载的方法简单 4继承引用计数类,来为自身增加引用技术功能, 引用计数的++ --在智能指针里完成 #i

第5章(2) Java的垃圾回收器

终结处理 Java有垃圾回收器回收无用对象占据的内存资源.但垃圾回收器只知道释放经由new分配的内存,如果用其他的方法获得了一块"特殊"的内存区域,就需要我们自己完成清理工作.Java提供了finalize()方法来解决这一问题. finalize()方法: 工作原理:一但垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存. 其作用,换句话说就是:在你不再需要某个对象之前,如果必须执行某些动作,那么你

垃圾回收器如何确定哪些对象要回收---《深入理解java虚拟机》

垃圾回收器如何确定哪些对象要回收: 引用计数法 很多教科书判断对象是否存活的算法是这样的:给对象添加一个引用计数器,每当有一个地发引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器都为0的对象就是不可能再被使用的. 客观地说,引用技术算法的实现简单,判定效率也很高,在大部分情况下它都是一个不错的算法,也有一些比较著名的应用案例,例如微软的COM技术.使用ActionScript 3 的FlashPlayer.Python语言以及在游戏脚本领域中被广泛应用的Squirrel中都

C++垃圾回收器的实现

一.简单介绍 这是一个自己写C++垃圾自己主动回收器,用到的都是标准C++语法.採用了引用计数加mark-sweep的方法.在没有循环引用的情况下,引用计数能够保证垃圾实时得到回收:对于有循环引用的情况下,计数就不能回收了,这时就要用mark-sweep的方法.事实上全然使用mark- sweep的方法也是能够的,但有了引用计数,能够回收大量的非循环引用垃圾,降低最后的mark-sweep时的工作量. 考虑到大家的15分钟阅读热情,在说细节之前,先show一下这个指针怎么使用.顺便提一下,这个指

谈一谈垃圾回收器

目的: 使用垃圾回收器的唯一原因就是:回收程序不再使用的内存. 针对的目标对象: Java的垃圾回收器会自动回收不再使用的Java对象,释放内存.但是回收的是用new创建的,分配在堆上的内存. finalize(): 那么,如果不是用这种方式创建的对象,该怎么回收?比如:Java调用了本地的c语言方法创建了个对象,那么这时,该对象不是放在堆上的.除非你手动去调用c的free()方法,否则,这个对象将永远不会被清理. Java的finalize()方法可以解决上面的问题.垃圾回收器在回收垃圾对象时