`
m635674608
  • 浏览: 4952444 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

JAVA 垃圾收集器与内存分配策略

 
阅读更多

引言

    垃圾收集技术并不是Java语言首创的,1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言。垃圾收集技术需要考虑的三个问题是:

  1. 哪些内存需要回收

  2. 什么时候回收

  3. 如何回收

    http://my.oschina.net/jiangmitiao/blog/470426 中讲到java内存运行时区域的分布,其中程序计数器,虚拟机栈,本地方法区都是随着线程而生,随线程而灭,所以这几个区域就不需要过多考虑回收问题。但是堆和方法区就不一样了,只有在程序运行期间我们才知道会创建哪些对象,这部分内存的分配和回收都是动态的。垃圾收集器所关注的就是这部分内存。

 

一 对象死亡判据

    垃圾收集器在对一个对象回收之前,首先要判断对象在程序中是否还有使用的可能性,充要条件就是没有被程序可访问引用再指向这个对象实例。最简单的办法就是给对象实例添加中添加一个引用计数器,每当有一个引用指向它时,计数器就加一,当引用失效时,计数器就减一,如果计数器值为0则说明没有引用指向它,可以进行回收。但是这个方法中计数器为0并不是一个必要条件,例如,生成两个对象实例,每个对象实例的属性都指向对方,那么这个两个对象实例分别最少有一个引用。

    java采用的是可达性分析算法,即找一部分对象作为"GC Roots"节点,从这些节点开始向下搜索,当某个对象到"GC Roots"节点没有可达路径时,说明此对象是不可用的。在java中作为"GC Roots"的节点包括:虚拟机栈中引用的对象,方法区静态属性引用的对象,方法区常量引用的对象,本地方法区中本地调用所引用的对象。

     引用扩充    

    如果reference类型的数据中存储的数值是另一块内存的起始地址,那么这块内存就代表着一个引用。一个对象在这种状态下,只能有被引用和没有被引用两种状态。java对引用概念进行了扩充,将引用分为强引用(new),软引用(softReference),弱引用(WeakReference),虚引用(PhantomReference)。如果强引用存在,则垃圾收集器不会回收该对象。如果系统即将发生内存溢出异常,那么垃圾回收集器则会回收软引用对象。弱引用对象只能存活到下一次垃圾收集之前。虚引用对象不会对其生存时间构成任何影响。

    对象的自我救赎

    在垃圾收集器发现某一个对象到"GC Roots"路径不可达时,先会判断该对象是否覆盖finalize()方法,或是否执行过finalize()方法。如果覆盖了且没有执行过该方法,则会将该对象放到低优先级的Finalizer线程中去执行finalize()方法,如果在finalize()方法中该对象又被引用,则会有一次逃脱被回收的命运。

    方法区的回收

    方法区中主要回收废弃的常量和无用的类。对于常量,如果没有引用指向常量,则该常量会被回收。对于类的回收则麻烦许多,首先要判断该类是无用的类,无用的类要满足三个条件:1所有类的实例被回收2加载该类的ClassLoader已经被回收3Class没有被引用,不会通过反射访问该类的方法。

 

二 垃圾回收算法

    标记-清除算法(Mark-Sweep)

    该算法分为两个阶段:首先标记处要回收的对象,标记完成后统一回收所有被标记的对象。

    存在的问题:1 标记和清除效率都不高 2 标记清除后会产生大量内存碎片,分配大对象时可能触发另一次垃圾收集。

    复制算法(Copying)

    该算法将内存分为两个等大小的区域,每次只使用一个区域。当一个区域快用完了,就将这个区域中存活的对象复制到另一个区域

    优点是避免了内存碎片的产生,缺点是浪费内存空间。

    有公司研究表明,新生代的对象98%都是朝生暮死,所以虚拟机把新生代内存划分为一个较大的Eden空间和两个较小的Survivor空间。每次只是用Eden空间和一个Survior空间,当进行复制清理时,将Survivor空间和Eden空间中存活的对象复制到另一块Survivor空间。当Survivor空间不够用时,就会依赖老年代进行分配担保。

    标记-整理算法(Mark-Compact)

    针对老年代对象存活率高的情况,复制算法明显不合适,于是采用标记整理算法,标记和标记清除算法相同,二后边的整理则是让所有存活的对象都向一端移动,然后清理掉边界外的内存。

    分代收集

    当前虚拟机都采用分代收集,分代的依据是对象的存活周期。一般新生代存活率低,采用复制算法。老年代存活率高采用标记整理或标记清除。

 

三垃圾收集器

由于虚拟机采用了分代收集,所以针对不同代收集器也不同。上图是HotSpot虚拟机的垃圾收集器,连线表示可以协同工作。

Serial收集器,复制算法,它是一个单线程的收集器,并且在进行收集时会暂停其他线程,它默认是client模式下的新生代收集器。

ParNew收集器是Serial收集器的多线程版,它是第一款并发收集器。

Parallel Scavenge收集器可以精确控制吞吐量(用户代码运行时间/(用户代码时间+垃圾收集时间))

 

SerialOld收集器是serial收集器的老年版,采用标记整理算法,同样是单线程收集器。

ParallelOld是ParallelScavenge收集器的老年版,使用多线程和标记整理算法。

CMS收集器是以最短回收停顿时间为目标的收集器,采用标记清除算法,在重视响应速度的系统中得以应用。但是缺点是对CPU资源敏感,无法处理浮动垃圾,易产生内存碎片。

 

G1收集器是最新推出的收集器,可应用在JDK1.7u4及以上版本。它将内存分为多个Region,新生代和老年代分别包含多个Region。G1跟踪各个Region,判断垃圾价值大小,优先回收价值最大的Region。

 

四 内存分配与回收策略

    对象的分配,就是在堆上分配,对象主要分配在新生代的Eden区域中,如果启动了本地线程分配缓冲,则按线程优先在TLAB中分配。少数情况也有可能直接分配到老年代。

    对象在Eden区域分配时,当Eden区域没有足够空间,虚拟机会发起一次新生代垃圾收集。

    如果对象需要大量连续内存空间,例如String类型和数组。大对象对于虚拟机内存分配来说是一个坏消息,朝生暮死的大对象是要命的坏消息。经常出现大对象会导致多次出发垃圾收集。对于这类对象,可以设置参数将大对象直接存入老年代。

    每一个对象都有一个年龄计数器,当对象在Eden区域出生,每经过一次GC,并且存入Survivor,计数器加一。当年龄增加到一定程度(默认15),则会被存入老年代。同时,如果Survivor空间中相同年龄对象占空间超过50%,则也会直接进入老年代。

    

总结

垃圾收集算法:复制算法,标记-清除算法,标记-清理算法。

垃圾收集器特点:新生代用复制,老年代用标记清理,CMS用标记清除。

Eden空间大小和Survivor空间大小默认比率为8:1,即新生代10%的空间用来存放复制后的对象。

 

 

http://m.oschina.net/blog/483654

分享到:
评论

相关推荐

    【Java正来-Java虚拟机专题】-Java垃圾收集器与内存分配策略

    主要整理内容为:分析了垃圾收集的算法和JDK1.7中提供的7款垃圾收集器的特点以及运作原理。以及内存分配策略

    JAVA 垃圾收集器与内存分配策略.rar

    JAVA 垃圾收集器与内存分配策略.rar

    JAVA垃圾收集器与内存分配策略详解

    介绍了JAVA垃圾收集器与内存分配策略,需要了解的朋友可以参考下

    深入java虚拟机

    1. JVM调优 1.1 JVM调优总结(一)-一些概念 1.2 JVM调优总结(二)-一些概念 1.3 JVM调优总结(三)-基本垃圾回收算法 1.4 JVM调优总结(四)-垃圾...4.2 JVM内存管理:深入垃圾收集器与内存分配策略 4.3 深入理解JVM

    详细介绍Java垃圾回收机制.docx

    引用计数收集器是垃圾收集器中的早期策略。在这种方法中,堆中每个对象(不是引用都一个引用计数。当一个对象被创建时,且将该对象分配给一个变量,该变量计数设置为1。当任何其它变量被赋值为这个对象的引用时,...

    JVM(Java虚拟机)

    JVM(Java虚拟机)的整个流程:发展,运行区域,垃圾回收器,内存分配策略,垃圾收集,JVM分析工具,JVM优化

    java jvm垃圾回收

    最后面两句将 object1 和 object2 赋值为 null,也就是说 object1 和 object2 指向的对象已经不可能再被访问,但是由于它们互相引用对方,导致它们的引用计数器都不为 0,那么垃圾收集器就永远不会回收它们。...

    深入理解_Java_虚拟机 JVM_高级特性与最佳实践

    / 41 2.5 本章小结 / 42 第3章 垃圾收集器与内存分配策略 / 43 3.1 概述 / 43 3.2 对象已死? / 44 3.2.1 引用计数算法 / 44 3.2.2 根搜索算法 / 46 3.2.3 再谈引用 / 47 3.2.4 生存还是死亡? / 48 3.2.5 ...

    java虚拟机精讲(电子工业出版社出版)

    本书以极其精练的语句诠释了 HotSpot VM的方方面面,比如:字节码的编译原理、字节码的内部组成结构、通过源码的方式剖析 HotSpot VM 的启动过程和初始化过程、Java 虚拟机的运行时内存、垃圾收集算法、垃圾收集器...

    Java虚拟机

    第3章 垃圾收集器与内存分配策略 3.1 概述 3.2 对象已死吗 3.2.1 引用计数算法 3.2.2 可达性分析算法 3.2.3 再谈引用 3.2.4 生存还是死亡 3.2.5 回收方法区 3.3 垃圾收集算法 3.3.1 标记-清除算法 3.3.2 ...

    jvm内存管理和垃圾回收

    很久之前就一直在学习JVM,但是一直也没有好好的总结,最近终于有了空闲,将之前学习的内容整理成了一个PPT。 也希望大神们可以批评指正。 ppt中主要包含下面几部分: Java内存模型 ... 垃圾收集器

    Java垃圾回收机制

    在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给了JVM来处理。顾名思义,垃圾回收是释放垃圾占用的空间,那么在Java中,什么样的对象会被认定为“垃圾”?那么当一些对象被确定为垃圾之后...

    Java新生代老年代的划分及回收算法

    当前JVM对于堆的垃圾回收,采用分代收集的策略。根据堆中对象的存活周期将堆内存分为新生代和老年代。在新生代中,每次垃圾回收都有大批对象死去,只有少量存活。而老年代中存放的对象存活率高。 这样划分的目的是...

    JVM核心知识学习和整理.docx

    JVM,JVM内存结构、HotSpot 虚拟机对象探秘、垃圾收集策略与算法、HotSpot 垃圾收集器、内存分配与回收策略、JVM 性能调优、类文件结构。。

    操作系统(内存管理)

    文中将为您提供如何管理内存的细节,然后将进一步展示如何手工管理内存,如何使用引用计数或者内存池来半手工地管理内存,以及如何使用垃圾收集自动管理内存。 为什么必须管理内存 内存管理是计算机编程最为基本的...

    resin-jvm 调优

    理解了应用程序的工作负荷和jvm支持的垃圾收集算法,便可以进行优化配置垃圾收集器。 垃圾收集的目的在于清除不再使用的对象。gc通过确定对象是否被活动对象引用来确定是否收集该对象。gc首先要判断该对象是否是...

    java8集合源码分析-AboutJava:java相关知识(理论,代码)相关知识均是看书,博客等地方获取再由自己整理,如存在侵权,请告诉我

    java8 集合源码分析 AboutJava ==java 相关知识(理论,代码)相关知识均是看书,博客等地方获取再由自己整理,如存在侵权,请告诉我== Java基础 ...垃圾收集器和内存分配策略 虚拟机性能监控工具 编程规范

    深入理解JVM内存结构及运行原理全套视频加资料.txt

    包括JVM执行过程、虚拟机类加载机制、运行时数据区、GC、类加载器、内存分配与回收策略等,全套视频加资料高清无密码  第1讲 说在前面的话 免费 00:05:07  第2讲 整个部分要讲的内容说明 免费 00:06:58  第3讲...

    leetcode回朔与贪心的题目-interview:面试官的编程

    垃圾收集器与内存分配策略 2.3 类加载机制 2.4 JVM 内存模型 2.5 JVM 性能监控工具与调优 2.5.1 jps 2.5.2 jstat 2.5.3 jinfo 2.5.4 jmap 2.5.5 jhat 2.5.6 jstack 2.5.7 jConsole 3. 多线程 3.1 线程的通信与状态...

    leetcode题库-java-interview:Java研发基础相关

    内存分配与回收策略 类加载 参数优化 进程与线程的区别 进程通信 创建线程的方式 线程的状态转换 线程安全 上下文切换 死锁 同步 异步 阻塞 非阻塞 synchronized & Lock volatile ThreadLocal sleep & wait 线程通信...

Global site tag (gtag.js) - Google Analytics