JVM内存回收机制涉及的知识点太多了,了解越多越迷糊,汗一个,这里仅简单做个笔记,主要参考《深入理解Java虚拟机:JVM高级特性与最佳实践(第二版)》

目前java的jdk默认虚拟机为HotSpot,因此本文涉及虚拟机相关内容都指HotSpot虚拟机

本文主要关注GC的回收:判断哪些对象可回收,如何回收,回收机制

判断哪些对象可回收

GC是通过对象是否存活来决定是否进行回收,判断对象是否存活主要有两种算法:引用计数算法、可达性分析算法

  • 引用计数算法
    引用计数的算法原理是给对象添加一个引用计数器,每被引用一次计数器加1,引用失效时减1,当计数器0后表示对象不在被引用,可以被回收了,引用计数法简单高效,但是存在对象之间循环引用问题,可能导致无法被GC回收,需要花很大精力去解决循环引用问题
  • 可达性分析算法
    可达性分析的算法原理是从对象根引用(堆栈、方法表的静态引用和常量引用区、本地方法栈)开始遍历搜索所有可到达对象,形成一个引用链,遍历的同时标记出可达对象和不可达对象,不可达对象表示没有任何引用存在,可以被GC回收

如何回收

  找到可回收对象后,如何进行回收呢?

  内存回收算法主要有标记-清除、停止-复制、标记-整理,不同算法使用不同的场景,总体来说停止-复制算法适合对象存活时间短,存活率低的新生代,标记-清除和标记-整理算法适合对象存活时间长,存活率高的老年代

  • 标记-清除(Mark-Sweep)
    通过可达性分析算法标记所有不可达对象,然后清理不可达对象。这种算法会形成大量的内存碎片
  • 停止-复制(Stop-Copy)
    将新生代内存按照8:1:1的比例分为一个eden区和两个survivor(survivor0,survivor1)区,回收时先将eden区存活对象复制到一个survivor0区,然后清空eden区,当这个survivor0区也存放满了时,则将eden区和survivor0区存活对象复制到另一个survivor1区,然后清空eden和这个survivor0区,此时survivor0区是空的,然后将survivor0区和survivor1区交换,即保持survivor1区为空, 如此往复,当survivor1区不足以存放 eden和survivor0的存活对象时,就将存活对象直接存放到老年代(这时我们可能回想,若是老年代也满了咋办,若是老年代也满了就会触发一次Full GC,也就是新生代、老年代都进行回收,若是内存还不够呢。。。,还不够那不废话了吗,OutOfMemory,不陌生吧哈哈)。从停止-复制算法的原理上我们可以看到,这种算法对于存活率较低的对象回收有着非常高的效率,而且不会形成内存碎片,但是会浪费一定的内存空间,适合对象存活率较低的新生代使用,如果在对象存活率较高的老年代采用这种算法,那将会是一场灾难
  • 标记-整理(Mark-Compact)
    通过可达性分析算法标记所有不可达对象,然后将存活对象都向一个方向移动,然后清理掉边界外的内存。这种算法是将存活对象向着一个方向聚集,然后将剩余区域清空,这种算法适合对象存活率较高的老年代

GC回收机制:分代收集算法

JVM内存收集算法基本上都是采用分代收集算法,即将内存划分为新生代、老年代,也有人把方法区算做永久代

  • 新生代
    对象被创建时,内存分配都是发生在新生代(大对象直接分配在老年代),绝大多数对象都是朝生夕灭,创建后很快就会不在使用,变为不可达的对象,被GC回收掉。新生代的对象存活率很低(到底有多低?研究表明有高达98%的对象创建后很快就消亡,想象一下平时编程,除了全局变量,局部变量在退出调用方法后还有几个能存活),存活时间都很短,新生代发生的GC也叫做Minor GC,MinorGC发生频率比较高(不一定等Eden区满了才触发)
  • 老年代
    当对象在新生代发生了多次Minor GC后仍然存活的对象即进入老年代,老年代的对象比新生多很多,当然了内存比新生代也大很多(大概比例是1:2,即新生代占用堆内存总量的1/3),当老年代内存满时触发Major GC即Full GC,Full GC发生频率比较低,老年代对象存活时间比较长,存活率标记高

一般来说我们所说的GC都是发生在新生代和老年代,新生代对象存活时间短,存活率低一般采用停止-复制算法,老年代对象存活时间长,存活率高,一般采用标记-整理、标记-清楚算法,具体采用何种算法和具体采用的垃圾收集器有关

GC里面有些类似未成年人和成年人,新创建的对象为新生代,新生代想要成为老年代需要经过一定的成长(总得一点点长大是吧),新创建的对象年龄为1,每发生一次Minor GC,存活对象的年龄增加1,当经历了15次Minor GC后,仍然存活的对象达到15岁,成达到法定成年年龄15岁(默认是15),正式成为成年人(老年代),对象成年后也就没有了年龄概念,直到对象死亡,会一直呆在老年代,当然也有一些老不死的(静态变量、常量等),会与世长存,除非地球灭亡(GC崩溃)

GC收集器

GC采用分代回收算好后,起着重要作用的是GC收集器,GC收集器分为新生代收集器和老年代收集器,不同的收集器使用不同的收集算法,有着不同的特点,由于目前的收集器在内存回收时无法消除(Stop-the-world),即在回收内存时不可避免的停止用户线程,目前的收集器只能使停顿时间越来越短,但是无法彻底消除,主要的收集其中Parallel Scavenge和Parallel Old是追求吞吐量为目标,其它的收集器都是追求高响应,低停顿,

  新生代收集器:Serial、PraNew、Parallel Scavenge

  老年代收集器:Serial Old、Parallel Old、CMS

  • Serial收集器(复制算法)
    新生代单线程收集器,标记和清理都是单线程,优点是简单高效。
  • Serial Old收集器(标记-整理算法)
    老年代单线程收集器,Serial收集器的老年代版本。
  • ParNew收集器(停止-复制算法)
    新生代收集器,可以认为是Serial收集器的多线程版本,在多核CPU环境下有着比Serial更好的表现。
  • Parallel Scavenge收集器(停止-复制算法)
    并行收集器,追求高吞吐量,高效利用CPU。吞吐量一般为99%, 吞吐量= 用户线程时间/(用户线程时间+GC线程时间)。适合后台应用等对交互相应要求不高的场景。
  • Parallel Old收集器(停止-复制算法)
    Parallel Scavenge收集器的老年代版本,并行收集器,吞吐量优先
  • CMS(Concurrent Mark Sweep)收集器(标记-清理算法)
    高并发、低停顿,追求最短GC回收停顿时间,cpu占用比较高,响应时间快,停顿时间短,多核cpu 追求高响应时间的选择
  • G1(Garbage-First)收集器(标记-整理算法、停止复制算法)
    GC最新型号,高富帅,高并发、可预测停顿、分代收集,不出意外未来主流将会逐步替代CMS,g1模糊了分代概念,虽然还是分为新生代和老年代,但是新生代和老年代不再是物理隔离,而是将内存分为n个region,以region为清理单位,整体采用标记-整理算法,region内部使用停止-复制算法。

JVM内存回收机制简述的更多相关文章

  1. JVM内存回收机制

    1. JVM内存回收机制简述 http://www.cnblogs.com/lzrabbit/p/3826738.html

  2. JVM内存回收机制——哪些内存需要被回收(JVM学习系列2)

    上一篇文章中讨论了Java内存运行时的各个区域,其中程序计数器.虚拟机栈.本地方法栈随线程生灭,且创建时需要多少内存,基本上在译期间就决定的了,所以在内存回收时无需特殊的关注.而堆和方法区则不同,首先 ...

  3. Java jvm 内存回收机制

    http://blog.csdn.net/yaerfeng/article/details/51291903 在Java中,它的内存管理包括两方面:内存分配(创建Java对象的时候)和内存回收,这两方 ...

  4. 深入理解JVM内存回收机制(不包含垃圾收集器)

    目录 垃圾回收发生的区域 如何判断对象是否可以被回收 HotSpot实现 垃圾回收算法 JVM中使用的垃圾收集算法 GC的分类 总结 参考资料 垃圾回收发生的区域 堆是java创建对象的区域(Stri ...

  5. Java技术专题之JVM逻辑内存回收机制研究图解版

    一.引言 JVM虚拟机内存回收机曾迷惑了不少人,文本从JVM实现机制的角度揭示JVM内存回收的原理和机制. 一.Java平台逻辑架构 二.JVM物理结构 通过从JVM物理结构图我们可以看到: 1.JV ...

  6. Java进阶3. 内存回收机制

    Java进阶3. 内存回收机制 20131029 前言: 学过C++的都知道,C++中内存需要程序员自己维护.说道这里,很多开发的同学就感觉很痛苦,当他转向Java的时候,就会说你看Java多好啊,程 ...

  7. JVM内存管理和JVM垃圾回收机制

    JVM内存管理和JVM垃圾回收机制(1) 这里向大家描述一下JVM学习笔记之JVM内存管理和JVM垃圾回收的概念,JVM内存结构由堆.栈.本地方法栈.方法区等部分组成,另外JVM分别对新生代和旧生代采 ...

  8. JVM内存管理、JVM垃圾回收机制、新生代、老年代以及永久代

    内存模型 JVM运行时数据区由程序计数器.堆.虚拟机栈.本地方法栈.方法区部分组成,结构图如下所示. JVM内存结构由程序计数器.堆.栈.本地方法栈.方法区等部分组成,结构图如下所示: 1)程序计数器 ...

  9. JVM 垃圾回收机制和常见算法和 JVM 的内存结构和内存分配(面试题)

    一.JVM 垃圾回收机制和常见算法 Sun 公司只定义了垃圾回收机制规则而不局限于其实现算法,因此不同厂商生产的虚拟机采用的算法也不尽相同.GC(Garbage Collector)在回收对象前首先必 ...

随机推荐

  1. MMS搜索功能修改

    高通平台的MMS源码中提供了搜索功能,但要先选择分类(名字,号码,信息内容,彩信主题),再输入字符,根据分类进行搜索. 而在Contacts中却不需要分类,直接根据输入字符搜索任意匹配字段.相比之下, ...

  2. javascript高级特性

    01_javascript相关内容02_函数_Arguments对象03_函数_变量的作用域04_函数_特殊函数05_闭包_作用域链&闭包06_闭包_循环中的闭包07_对象_定义普通对象08_ ...

  3. Android视图状态及重绘流程分析,带你一步步深入了解View(三)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17045157 在前面一篇文章中,我带着大家一起从源码的层面上分析了视图的绘制流程, ...

  4. $(function(){})、$(document).ready(function(){})....../ ready和onload的区别

    1.window.onload 当一个文档完全下载到浏览器中时,会触发 window.onload 事件. 这意味着页面上的全部元素对 javascript 而言都是可以访问的,这种情况对编写功能性的 ...

  5. FibonacciSequence

    import java.util.Scanner; public class Fibonacci { public static void main(String[] args) { int n; f ...

  6. Features

    imhist分析灰度图阈值分界点 bwlabel分析连通区域 SIFT Scale Invariant:尺度不变性 DoG: Difference of Gaussian, calculated by ...

  7. js获取div相对屏幕的坐标位置

    1:div相对屏幕的坐标位置 function getDivPosition(div){ var x = div.getBoundingClientRect().left; var y = div.g ...

  8. java 获取本地电脑的分辨率代码

    1.代码: java.awt.Toolkit tk=java.awt.Toolkit.getDefaultToolkit();       java.awt.Dimension screenSize= ...

  9. swift 如何给tabBarItem的相关设计

    //设置tabBarItem的title,以及点击和不点击状态图片 self.tabBarController.tabBarItem = UITabBarItem(title: "投资理财& ...

  10. CDATA为何物?

    CDATA的解释 1. 术语 CDATA 指的是不应由 XML 解析器进行解析的文本数据(Unparsed Character Data),XHTML也是如此. CDATA 部分中的所有内容都会被解析 ...