如何判断垃圾对象?

垃圾收集的第一步就是先需要算法来标记哪些是垃圾,然后再对垃圾进行处理。
 
引用计数(ReferenceCounting)算法
这种方法比较简单直观,FlashPlayer/Python使用该算法,简单高效。核心思路是,给每个对象添加一个被引用计数器,被引用时+1,引用失效-1,等于0时就表示该对象没有被引用,可以被回收。但是,Java/C#并不采用该算法,因为该算法没有解决对象相互引用的问题,即:当两个对象相互引用且不被其它对象引用时,各自的引用计数为1,虽不为0,但仍然是可被回收的垃圾对象。
 
根搜索(GC Roots Tracing)算法
基本原理是:GCRoot对象作为起始点(根)。如果从根到某个对象是可达的,则该对象称为“可达对象”(存活对象,不可回收对象)。否则就是不可达对象,可以被回收。
 

垃圾收集算法

垃圾收集器通常会假设大部分的对象的存活时间都非常短,只有少数对象的存活时间比较长。
垃圾收集算法在JVM中主要是复制算法(新生代GC)和标记/整理算法(老年代GC)。
 
标记-清除(Mark-Sweep)算法
算法过程:
1. 先判定对象是否可回收,对其标记。
2. 统一回收(简单地删除对垃圾对象的内存引用)。
优点:简单直观容易实现和理解。缺点:效率不高,内存空间碎片化。
 
复制(Copying)算法
将内存平均分成A、B两块,算法过程:
1. 新生对象被分配到A块中未使用的内存当中。当A块的内存用完了, 把A块的存活对象对象复制到B块。
2. 清理A块所有对象。
3. 新生对象被分配的B块中未使用的内存当中。当B块的内存用完了, 把B块的存活对象对象复制到A块。
4. 清理B块所有对象。
5. goto 1。
优点:简单高效。缺点:内存代价高,有效内存为占用内存的一半。
 
对复制算法进一步优化:使用Eden/S0/S1三个分区
平均分成A/B块太浪费内存,采用Eden/S0/S1三个区更合理,空间比例为Eden:S0:S1==8:1:1,有效内存(即可分配新生对象的内存)是总内存的9/10。
算法过程:
1. Eden+S0可分配新生对象;
2. 对Eden+S0进行垃圾收集,存活对象复制到S1。清理Eden+S0。一次新生代GC结束。
3. Eden+S1可分配新生对象;
4. 对Eden+S1进行垃圾收集,存活对象复制到S0。清理Eden+S1。二次新生代GC结束。
5. goto 1。
 
标记-紧凑(Mark-Compact)
算法过程:
1. 标记:标记可回收对象(垃圾对象)和存活对象。
2. 紧凑(也称“整理”):将所有存活对象向内存开始部位移动,称为内存紧凑(相当于碎片整理)。完毕后,清理剩余内存空间。
 
分代收集策略
由于不同的对象适合使用不同的垃圾收集算法,所以引入“代”这个概念。不同的代有不同的分区,一般分为新生代区和老年代区。
新生代:适合采用复制算法进行垃圾收集,对象分布在Eden/S0/S1三个区。
老年代:适合采用标记-紧凑算法进行垃圾收集。
 

Heap分区和分代概念

Heap分区的目的
1. 为了分代:不同代的对象放到不同的内存分区中,实现“代提升”,也方便实现对不同分代采用不同的垃圾收集算法。
2. 垃圾收集算法需要:新生代GC使用到复制算法,该算法需要将对应的分区划分成三个分区:Eden/S0/S1。
 
术语
Generation代
 - YongGeneration/NewGeneration:新生代,在Eden/S0/S1的存活的对象。
 - OldGeneration:老年代,在Tenured区存活的对象。
 - PermanentGeneration:永久代。
Space 区
 - Eden:伊甸园区,是新生代的一个区。
 - Survivor:幸存区,属于新生代,为了复制算法的需要。一般分成大小相等的两个区(S0/S1或者From/To)。
 - Tenured:存放老年代的区域。
 - Permanent:终身区。

 
下图:Hotspot 的 Heap 分区
 
 
下图:VisualVM 中通过 VisualGC插件显示的分区
 
 
Eden/S0/S1 新生代
[Eden                 ][S0     ][S1    ]
S0/S1是大小相当的两个区域,共同组成Survivor区。
空间比例:Eden:S0==8:1。设定方法:-XX:SurvivorRatio=8。
新生对象在Eden/S0或者Eden/S1中分配,Eden区的对象量达到一个阈值后,发生一次新生代GC。
 
Old 老年代
每个对象有“对象年龄计数器”。对象由Eden收集到Survivor区后,年龄+1。进行新生代GC后,年龄+1。依次,当年龄>=15后进入老年代。
最大年龄阈值设定:-XX:MaxTenuringThreshold。
动态年龄:如果在Survivor中所有相同年龄对象占用了空间的一半多,大于等于上述年龄的对象直接进入老年代。
大对象(比如大的数组)直接进入老年代。阈值设定:-XX:PretenureSizeThreshold。
 
Perm 永久代(PermanentGeneration)
用于存放不变对象,如类、方法、字符串等。
Java7把驻留字符串(intentd string)放到了老年代区。Java8中移除了Hotspot的永久代区。
 

Refs

《深入理解Java虚拟机》

JVM中的垃圾收集算法和Heap分区简记的更多相关文章

  1. WordCount作业提交到FileInputFormat类中split切分算法和host选择算法过程源码分析

    参考 FileInputFormat类中split切分算法和host选择算法介绍  以及 Hadoop2.6.0的FileInputFormat的任务切分原理分析(即如何控制FileInputForm ...

  2. 【JVM】JVM中的垃圾收集器

    垃圾收集器组合 Serial+Serial Old Serial+CMS ParNew+CMS ParNew+Serial Old Paralle Scavenge + Serial Old Para ...

  3. 串匹配模式中的BF算法和KMP算法

    考研的专业课以及找工作的笔试题,对于串匹配模式都会有一定的考察,写这篇博客的目的在于进行知识的回顾与复习,方便遇见类似的题目不会纠结太多. 传统的BF算法 传统算法讲的是串与串依次一对一的比较,举例设 ...

  4. js中各个排序算法和sort函数的比较

    js中要实现数据排序,其实只需要用sort函数就能很好的满足了,但是我今天想知道他和其他排序算法的区别,比如耗时呀等.测了一组数据如下: // ---------- 一些排序算法 Sort = {} ...

  5. JVM中的垃圾收集

    引用计数(Reference Counting) 循环引用问题 标记­清除(Mark and Sweep) 内存池(Memory Pools) Eden 是内存中的一个区域, 用来分配新创建的对象 . ...

  6. JVM(五)内存(Heap)分配

    前面的两小节,我分享了一下JVM的垃圾回收算法和垃圾回收器,本节中,我们来看看JVM的内存分配到底是如何进行的,作为对前面两节内存回收的补充. 从前面的内存回收中我们了解到,Hotspot JVM中的 ...

  7. 💕《给产品经理讲JVM》:垃圾收集器

    前言 在上篇中,我们把 JVM 中的垃圾收集算法有了一个大概的了解,又是一个阴雨连绵的周末,宅在家里的我们又开始了新一轮的学习: 产品大大:上周末我们说了垃圾收集算法,下面是不是要讲一下这些算法的应用 ...

  8. 【转】JVM运行原理及JVM中的Stack和Heap的实现过程

    来自: http://blog.csdn.net//u011067360/article/details/46047521 Java语言写的源程序通过Java编译器,编译成与平台无关的‘字节码程序’( ...

  9. JVM中的Stack和Heap

    Stack: 是内存指令区.Java基本数据类型,Java指令代码,常量都保存在stack中,方法是指令也保存在stack中. 由于stack是内存是顺序分配,而且定长,不存在内存回收问题.存取速度快 ...

随机推荐

  1. python数据处理相关的一些知识点(学习点)

    自己总结了一下就是存储,消息处理(异步,阻塞,队列,消息中间件) 参考岗位需求 数据爬虫工程师的岗位职责:1.分布式网络爬虫研发:不断完善现有抓取系统,通过对抓取.解析.调度.存储等模块的拆分与优化, ...

  2. c# (nop中)下拉列表(有外键)

    第一种情况.view视图加载出来时就有值,实现步骤如下 1.在操作的界面Model中建立public List<SelectListItem> xxx(取名){ get; set; } 2 ...

  3. java线程详解(二)

    1,线程安全 先看上一节程序,我们稍微改动一下: //线程安全演示 //火车站有16张票,需要从四个窗口卖出,如果按照上面的多线程实现,程序如下 class Ticket implements Run ...

  4. 学习angular 指令构造器时遇到的小问题

    在学习angular时,使用模块来为应用添加自己的指令时,遇到了一个问题,演示的代码如下: <!DOCTYPE html> <html> <head> <me ...

  5. 现在的SQLSERVER数据库监控软件有哪些?

    现在的SQLSERVER数据库监控软件有哪些? 收集了一下当前SQLSERVER数据库监控软件,发现开源免费的真的是“没有” Questsoftware  Quest's spotlight(收费)  ...

  6. CSS设计资料

    CSS实现垂直居中的5种方法 网页阶级配色:http://tools.jb51.net/tools/peise.htm

  7. Javascript中递归造成的堆栈溢出及解决方案

    关于堆栈的溢出问题,在Javascript日常开发中很常见,Google了下,相关问题还是比较多的.本文旨在描述如何解决此类问题. 首先看一个实例(当然你可以使用更容易的方式实现,这里我们仅探讨递归) ...

  8. Sublime Text 全程指南

    摘要(Abstract) 本文系统全面的介绍了 Sublime Text,旨在成为最优秀的 Sublime Text 中文教程. 更新记录 2014/09/27:完成初稿 2014/09/28: 更正 ...

  9. Atitit.javascript 实现类的方式原理大总结

    Atitit.javascript 实现类的方式原理大总结 1. 实现类的式::构造方法方式:原型方式:构造方法+原型的混合方式 1 2. 原型方式(function mode)经典式..实现属性推荐 ...

  10. atitit.表格的绑定client side 最佳实践

    atitit.表格的绑定client side 最佳实践 1. 框架选型 1 2. #---原理和流程 1 1. 方法1 1 2. Dwr 例子 1 3. 方法2 2 4. Jq例如 2 1. 框架选 ...