博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深入理解java虚拟机 - 垃圾回收机制(GC)
阅读量:5330 次
发布时间:2019-06-14

本文共 1733 字,大约阅读时间需要 5 分钟。

垃圾回收机制(GC)是java常重要特性之一。它让开发者无需关注内存的创建和释放,而是通过GC自动回收垃圾(无用对象)。

哪些内存需要回收

java堆和方法区是垃圾回收的主要内存区域,程序计数器、虚拟机栈、本地方法栈这几个内存区域是现成私有的,线程结束时内存自然也就回收了。

如何判断对象可回收?

在java堆里存放着几乎所有的对象实例,垃圾收集器在进行垃圾回收之前第一件事情就是判断哪些对象还"活着",哪些对象已"死去"(不会再被使用的对象);

引数记数法

引数记数法就是给对象添加一个引数计数器,每当有其他地方引用对象时,计数器就加1;当引用失效时,计数器就减1,如果计数器任何时刻都为0,那么对象不可能在被使用,垃圾收集器就可以进行回收了。引数记数法简单高效,微软公司的COM技术,python语言,游戏脚本语言Squirrel都是使用了引数记数法进行内存管理。但是主流java虚拟机没有使用引述记数法进行内存管理,原因主要是他很难解决对象之间互相引用的的问题。

可达性分析算法

java虚拟机是通过可达性分析算法来判定对象是否存活的。可达性分析算法的主要思想是通过一系列的称为"GC Roots"的对象作为起始点从这些起点开始向下搜索,搜索走过的路径称为引用链,当一个对象到"GC Roots"没有任何引用链相连时("GC Roots"到此对象不可达),则证明此对象是不可用,可回收的。

在java语言中,可作为"GC Roots"的对象包括以下几种

  • 虚拟机栈()中引用的对象
  • 方法区中类静态变量引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI引用的对象

垃圾收集算法

简单介绍下几种垃圾收集算法

标记-清除算法

最简单的垃圾收集算法是“标记-清除”算法,算法分为“标记”和“清除”两个阶段:首先要标记出需要回收的对象,在完成标记后统一回收所有被标记的对象。标记过程就是判断哪些对象需要回收。

标记-清除算法有两个不足之处:
一个是效率问题,标记-清除的效率都不高;
另一个空间问题,标记-清除之后会产生大量不连续的内存碎片,内存空间碎片太多可能会导致java虚拟机在分配较大对象时,无法找到足够的连续内存而触发一次垃圾收集动作。

1351714-20180727135257142-1939097425.png

复制算法

复制算法是为了解决标记-清除算法的效率问题而产生的。它是如何解决效率问题的呢?

复制算法将内存分为两块大小相等的两块,每次只使用其中一块。当这一块的内存用完了,将存活的对象复制到另一块上,然后将使用过的一块内存全部清理掉。这样每次都是对整个半区进行垃圾回收,内存分配时就不需要担心内存碎片的问题了。复制算法实现简单,运行高效。代价就是内存缩小为原来的一半。

1351714-20180727135414428-1939843564.png

复制算法主要用来回收新生代,IBM的专家研究过,新生代的中的对象98%都是“朝生夕死”的,并不需要按照1:1的比例来划分内存空间,而是将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次只使用Eden和其中一块Survivor空间。当进行垃圾回收时将Eden和Survivor中还存活的对象复制到另一块Survivor空间上,最后清理掉Eden和使用过的Survivor空间。Eden空间和两块Survivor空间之间的比例时8:1:1,新生代可用空间为90%(80% + 10%),只浪费了10%内存空间。当存活对象多于10%时,Survivor空间不够用,这些对象将通过直接进入老年代。

标记整理算法

老年代是通过标记-整理算法来进行垃圾回收的。标记过程与标记-清除算法一样,清除过程不是直接清理可回收对象,而是让所有的对象都向一端移动,然后直接清理掉边界以外的内存。

1351714-20180727135514652-476676768.png

分代收集算法

现代商业虚拟机的垃圾收集都采用“分代收集”算法,分代收集算法根据对象存活周期的不同将java堆内存分为新生代和老年代。新生代每次垃圾收集时大量对象死去,只有少量对象存活,那就使用复制算法。老年代中的对象存活率高,没有额外内存空间进行担保,那就使用标记清除算法或者标记整理算法。

垃圾收集器

未完。。。

参考资料

《深入理解java虚拟机》

转载于:https://www.cnblogs.com/renguangli/p/9377248.html

你可能感兴趣的文章
2018icpc徐州OnlineA Hard to prepare
查看>>
使用命令创建数据库和表
查看>>
【转】redo与undo
查看>>
wpf样式绑定 行为绑定 事件关联 路由事件实例
查看>>
Oracle事务
查看>>
String类中的equals方法总结(转载)
查看>>
内存地址对齐
查看>>
创新课程管理系统数据库设计心得
查看>>
Could not resolve view with name '***' in servlet with name 'dispatcher'
查看>>
管道,数据共享,进程池
查看>>
SDUTOJ3754_黑白棋(纯模拟)
查看>>
php中的isset和empty的用法区别
查看>>
把word文档中的所有图片导出
查看>>
ubuntu 18.04取消自动锁屏以及设置键盘快捷锁屏
查看>>
arcgis api 4.x for js 结合 Echarts4 实现散点图效果(附源码下载)
查看>>
YTU 2625: B 构造函数和析构函数
查看>>
apache自带压力测试工具ab的使用及解析
查看>>
加固linux
查看>>
Hyper-V虚拟机上安装一个图形界面的Linux系统
查看>>
字符串类型的相互转换
查看>>