一、Java的回收策略是:
回收已经“死了”的对象即不可能再被任何途径使用的对象
二、如何判断对象已经死了:
我们现在常用的方法是引用计数算法和根搜索算法
①引用计数算法的原理和弊端 :
原理:我们给对象 添加一个引用计数器,每当一个地方引用这个对象的时候,我们的计数器,就加1,当引用失效的时候,我们的计数器的值就减1;任何时刻计数器为0的对象就是不可能再被使用的,我们就判定为该对象已“死”;优点,实现简单,判定效率高;
弊端:很难解决对象间相互循环引用的问题;例如:对象A和对象B都有test 字段,领A.test = B.test;B.test = A.test;除此之外这两个对象再无任何引用;实际上这两个对象已经是 应该回收的 对象,但是他们相互引用,导致他们的计数器都不为0,这种情况下,引用计数算法就无法很好的解决这类问题;
②可达性分析算法:算法的基本思路就是通过一系列 成为GCRoots的对象那个作为根节点,从这些节点开始向下搜索,搜索的路径成为引用链,当一个对象到GCR哦哦图书没有任何引用链的时候,则认为此对象是不可用的;
③即使可达性分析算法判定为不可达的对象,也不是非死不可的,这时候是一个缓刑阶段,至少要经历两次标记的过程,如果可达性分析判定其没有与GCRoots相连的引用链的时候,则进行第一次标记并进行筛选,筛选的条件是此对象有没有必要执行finalize()方法。当对象没有覆盖finalize()方法或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都判定为“没有必要执行”;如果这个finalize()方法被判定为有必要执行 finalize()方法,那么这个对象将会被方最一个F-Queue的队列中,并在稍后由一个虚拟机自动创建的、低优先级的Finalizer县城去执行它;
④finalize()方法是对象逃脱死亡命运的最后一次机会,如果对象在finalize()方法中重新与引用链上的任何一个对象建立关联,则成功自救,否则这个对象基本上就真的被回收了;
finalize()的测试方法如下:
public class FinalizeEscapeGC { public static FinalizeEscapeGC SAVE_HOOK = null; public void isAlive(){ System.out.println("yes,i am alive"); } @Override protected void finalize() throws Throwable { super.finalize(); System.out.println("finalize method executed"); FinalizeEscapeGC.SAVE_HOOK = this; } public static void main(String[] args) throws InterruptedException { SAVE_HOOK = new FinalizeEscapeGC(); //对象的第一次自救 SAVE_HOOK = null; System.gc(); //因为finalize()的优先级很低 ,所以暂停1秒用来等待它 Thread.sleep(1000); if (SAVE_HOOK != null){ SAVE_HOOK.isAlive(); }else { System.out.println("no,i am dead"); } //与对象的第一次自救的代码完全相同,却失败了 SAVE_HOOK = null; System.gc(); Thread.sleep(1000); if (SAVE_HOOK != null){ SAVE_HOOK.isAlive(); }else { System.out.println("no,i am dead"); } } /** * 执行结果第一成功,第二次失败,因为任何一个对象的finalize()方法都只会被系统调用一次,如果对象面临下一次回收,他的finalize() * 方法不会再被执行,因此第二次失败 */ }
运行结果为:
finalize method executed yes,i am alive no,i am dead Process finished with exit code 0
虽然finalize()这个方法已经很悲情了,但是这个方法并不是一个好的方法,我们要尽量的避免使用它,因为他的运行代价高,不确定性大,无法保证各个对象的调用顺序,有些教材中描述他为“关闭外部资源”之类的工作,这完全是对这个方法的一种自我安慰,finalize()能做的所有工作,使用try-finally或者其他方式都可以做的更好更及时,所以我们可以忘了Java中拥有这样一个方法;
三、回收方法区
很多人认为方法区(或者Hotpot虚拟机中的永久代)是没有垃圾收集的,并且Java虚拟机规范中说过可以不要求虚拟机在方法区进行垃圾收集,并且在方法区中进行垃圾收集的性价比一般非常低;
永久代的垃圾收集主要回收两部分内容:废弃常量和无用的类
①回收废弃常量:
与回收Java堆中的对象十分类似;一常量池中字面量的回收为例,假如一个字符串“ABC”已经进入了常量池,但是当前系统中没有任何一个String对象是这个的,如果这时发生垃圾回收,而且必要的话,这个字符串常量会被系统清理出常量池,常量池中的其他类(接口)、方法、字段的符号引用也与此类似;
②回收无用类
:该类在所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例
:加载该类的ClassLoader已经被回收
:该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射来访问该类的方法
满足以上三个条件后,并不是必然会被回收是否被回收还要被虚拟机通过一些参数进行控制
四、垃圾收集算法
1、标记-清除法
这是最基础的算法,分为标记和清除两个阶段:首先标记处所有需要回收的对象,在标记完成后同意清除这些被标记的对象;
这个方法主要有两个不足:一个是清除效率过于低下,这两个过程的效率都不高;另外一个就是空间问题了,标记清除过后会产生大量的内存碎片,肯能导致以后在程序运行过程中需要分配较大对象的时候,无法找到足够的连续内存而 不得不提前出发另一次垃圾收集动作;
2、复制算法
为了解决效率问题,它将可用内存按照容量划分为大小相等的两块,每次只使用其中的一块。当一块的内存用完了,就将还存活着的对象复制到另一块上面,然后再把已经使用过内存空间一次清理掉。这样使得每次都是对整个半区进行内存回收,内存分配的时候也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效;
因为将内存缩小为了原来的一半,这样浪费太高了,因为新生代中的对象98%都是朝生夕死的,所以并不需要按照一比一的比例来华反内存空间,而是将内存分为一个Eden空间,两个Survivor空间,每次使用Eden空间和其中的一块Survivor空间。当回收时,将Eden和Survivor中还存活的对象一次性复制到另一块Survivor空间上,最后才清理掉Eden空间和刚才使用过的Survivor空间。HotSpot虚拟机默认的Eden和Survivor的比例是八比一,也就是每次只有10%的会被浪费,但是98%只是一般情况下,当特殊情况的时候,当Survivor空间不够用的时候,需要依赖其他没存(这里指老年代)进行分配担保;这些多出来的对象将直接通过分配担保机制进入老年代;
3、标记-整理算法
复制收集算法在对象存活率较高时就要进行较多的复制操作,效率将会变低。如果不想浪费50%的空间,就需要有额外的空间进行分配担保,以应对被使用过的内存中的对象都100%存活的极端情况,所以老年代中不能直接选用这种算法;
标记-整理算法也是分为两个阶段:第一阶段与标记-清除算法的第一阶段一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存;
4、分代收集算法
目前的商业虚拟机的垃圾收集都采用“分代收集”算法,该算法就是根据对象存活周期不同将内存划分为几个块,一般把Java堆区分为新生代和老年代,然后根据每一代的特点采用最适当的收集算法;新生代采用复制算法,老年代因为存活率较高、没有额外空间对其进行担保,于是采用标记-整理或标记-清除算法
相关推荐
Font Awesome图标字体库提供可缩放矢量图标,它可以被定制大小、颜色、阴影以及任何可以用CSS的样式
介绍了physical design的floorplanning问题
数学建模培训资料 数学建模实战题目真题答案解析解题过程&论文报告 最低生活保障问题的探索 共20页.pdf
变更用水性质定额申请表.xls
从官网上下载下来,作为资源存储,方便安装,此资源为windows版本
嗨玩旅游网站-JAVA-基于springboot嗨玩旅游网站设计与实现(毕业论文+PPT)
【资源说明】 本科毕业设计 基于Python中国知网(cnki)爬虫及数据可视化详细文档+全部资料.zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
api代码
【作品名称】:基于 Java 实现的24点卡牌游戏【课程设计】 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【项目介绍】: Java小游戏--24点卡牌游戏 将扑克牌(除大小王)随机打乱,每次出现4张卡牌,每张卡牌使用一次,13个回合。 A代表1,J代表11,Q代表12,K代表13。 可2-4人局域网同时在线对战,100秒倒计时结束前回答正确可获得积分,先回答的可获4分,后回答的分数依次递减。 实时显示玩家排名。 【资源声明】:本资源作为“参考资料”而不是“定制需求”,代码只能作为参考,不能完全复制照搬。需要有一定的基础看懂代码,自行调试代码并解决报错,能自行添加功能修改代码。
用 Python 实现的可扩展布隆过滤器皮布卢姆pybloom是一个包含 Bloom Filter 数据结构以及可扩展 Bloom Filter 实现的模块,如下所述P. Almeida、C.Baquero、N. Preguiça、D. Hutchison,可扩展布隆过滤器,(GLOBECOM 2007),IEEE,2007。如果您了解需要提前留出多少位来存储整个集合,那么布隆过滤器就是您的不二之选。可扩展布隆过滤器允许您的布隆过滤器位根据误报概率和大小进行增长。当过滤器达到容量上限时,即为“满”M * ((ln 2 ^ 2) / abs(ln p)),其中 M 是位数,p 是误报概率。当达到容量上限时,将创建一个比上一个过滤器大得多的新过滤器,其误报概率更小,哈希函数数量更多。>>> from pybloom import BloomFilter>>> f = BloomFilter(capacity=1000, error_rate=0.001)>>> [f.add(x) for x in range(10)][False, False, False,
计算机学院宿舍美化大赛.rar
基于java的运动器械购物商城设计与实现.docx
内容概要:文章介绍了针对“卓越工程师教育培养计划”,结合PBL和CDIO工程教育理念,对材料成型及控制工程专业课程设计的实践教学改革进行探索。首先在命题设计上依托企业实践项目,确保设计内容与生产实际紧密结合,具有较强的创新性和实用性。在过程管理中,采用分组合作和面向实际问题导向的教学方法,提升学生的工程素养和创新思维。通过课程设计的成绩考核,结合校内外导师的共同评价,客观全面衡量学生的学习成果。指导教师发挥了组织、支持和引导等多方面的角色作用。 适合人群:高等院校材料成型及控制工程专业学生和教学管理人员;工程教育领域的研究人员。 使用场景及目标:旨在提升工科学生的工程实践能力和创新能力,使其具备解决复杂实际工程问题的能力。通过改革教学内容和方法,改善传统课程设计中存在的不足,培养出高素质的技术人才。 其他说明:改革措施在实际运行中取得了较好的教学效果,提高了学生的就业竞争力,但仍存在一些不足之处需要在未来进行完善。
设计模式学习
C的两数相加求和的程序代码
Viper是一个基于Anno微服务引擎开发的Dashboard示例项目。Anno底层通讯采用grpc、thrift
本教程播放列表涵盖了 Python 中的数据结构和算法。每个教程都有数据结构或算法背后的理论、BIG O 复杂性分析和可供练习的练习。使用 Python 的数据结构和算法本教程涵盖了 Python 中的数据结构和算法。每个教程都包含数据结构或算法背后的理论、BIG O 复杂度分析以及可供练习的练习。要观看视频,您可以访问播放列表https://www.youtube.com/playlist?list=PLeo1K3hjS3uu_n_a__MI_KktGTLYopZ12订阅 codebasics youtube 频道https://www.youtube.com/c/codebasics
python入门——安装Python软件包
就业去向信息-JAVA-基于微信小程序高校毕业生实习及就业去向信息管理系统(毕业论文+PPT)
基于java的学费管理系统设计与实现.docx