java垃圾回收算法和垃圾收集器
垃圾收集算法、垃圾回收算法、java垃圾收集器
目录
1. 垃圾收集算法
1)引用计数法
2)根搜索法
2. 垃圾回收算法
1)复制算法
2)标记-清除算法
3)标记-整理算法
4)分代收集算法
3. java垃圾收集器
新生代GC器:
1)Serial垃圾收集器
2)ParNew垃圾收集器
3)Parallel Scavenge垃圾收集器
老年代GC器
1)Serial和Parallel Scavenge都有对应的老年代版本
2)CMS垃圾收集器
G1回收器
4.java对象的内存分配位置
5.java TLAB
6.java 何时触发GC
1) new gen对象什么时候会晋升到old gen中?
2) 什么时候会出现old gen空间不足(old gen空间不足时,会触发full gc)?
1. 垃圾收集算法
1)引用计数法
给对象添加引用计数器,当引用对象时计数器+1,引用失效时,计数器-1,当计数器等于0时,对象失效,内存可以被回收。
优点:实现简单高效。
缺点:对象之间的互相循环引用问题不好解决。
2)根搜索法
通过GC roots可达的对象路径称为引用链(reference chain),当一个对象没有引用链时(即从GC roots不可达)则视为不可用对象,内存可以被回收。java使用该算法进行垃圾收集。
哪些对象可以视为GC roots ?
a. 虚拟机栈中(即栈帧中的本地变量)的引用对象;
b. 本地方法栈中的引用对象;
c. 方法区(永久代)中的静态变量引用的对象和常量池中引用的对象
2. 垃圾回收算法
1)复制算法
将内存分为(大小相等)两部分,每次只使用其中一块进行内存分配,当内存使用完后,就出发GC,将存活的对象直接复制到另一块空闲的内存中,然后对当前使用的内存块一次性清除所有,然后转到另一块内存进行使用。
优点:简单,高效。
缺点:浪费内存,因为每次都有另一块内存空闲着。
2)标记-清除算法
分两步进行,第一步标记出可以回收的对象,第二步统一清理可以回收的对象内存。
缺点:首先标记和清除步骤效率都不高,其次会产生内存碎片。
3)标记-整理算法
类似于标记-清除算法,但是第二步进行内存回收时,将存活的对象向内存一端移动,达到消除内存碎片问题。
4)分代收集算法
java sun hotspot虚拟机将内存分为新生代(堆)、老年代(堆)、永久代(方法区、常量池、即时编译代码)几个区域,新生代主要使用基于复制算法的垃圾回收,老年代和永久代主要使用标记-整理算法进行垃圾回收。具体每个区域使用哪种垃圾回收算法还要视收集器的实现制约。


3. java垃圾收集器
新生代GC器:
1)Serial垃圾收集器:
单线程串行垃圾收集器,使用复制算法进行垃圾回收,GC时需要暂停所有用户线程,直到GC完成。
注:此处的串行垃圾收集器中的串行意义是指GC过程和用户线程执行过程是串行的,即GC过程中用户线程暂停,用户线程执行是,GC是不执行的。
2)ParNew垃圾收集器:
多线程串行垃圾收集器,Serial的多线程版本,其它特性同Serial。
3)Parallel Scavenge垃圾收集器:
类似于ParNew,但是该收集器关注的是cpu的吞吐量(throughput=user-cpu-time/total-cpu),通过参数-XX:GCTimeRation和-XX:MaxGCPauseMillis来控制吞吐量,是吞吐量优先的收集器,同样使用复制算法进行垃圾回收,GC过程需要暂停所有用户线程。
老年代GC器:
1)Serial和Parallel Scavenge都有对应的老年代版本:
Serial Old和Parallel Old垃圾收集器,它们与新生代的区别在于老年代区域的版本,采用标记-整理算法进行垃圾回收。
2)CMS垃圾收集器:
Concurrent Mark Sweep收集器,是真正意义上的多线程并行垃圾收集器,CMS在GC过程中的某些阶段用户线程是可以运行的,因此说它是真正意义上的并行垃圾收集器,前面介绍的垃圾收集器在GC过程中都要暂停用户线程,因此,视它们为与用户线程串行执行的垃圾收集器。CMS GC过程分四步完成:
a.初始标记:只是标记一下GC Roots能直接关联的对象,速度很快,仍然需要暂停所有的工作线程。
b.并发标记:进行GC Roots跟踪的过程,和用户线程一起工作,不需要暂停工作线程。
c.重新标记:为了修正在并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,仍然需要暂停所有的工作线程。
d.并发清除:清除GC Roots不可达对象,和用户线程一起工作,不需要暂停工作线程。
**G1回收器:
参考:http://www.importnew.com/15311.html
4. java对象的内存分配位置
1) 编译器通过逃逸分析,确定对象是在栈上分配还是在堆上分配。如果是在堆上分配,则进入选项2.
2) 如果tlab_top + size <= tlab_end,则在在TLAB上直接分配对象并增加tlab_top 的值,如果现有的TLAB不足以存放当前对象则3.
3) 重新申请一个TLAB,并再次尝试存放当前对象。如果放不下,则4.
4) 在Eden区加锁(这个区是多线程共享的),如果eden_top + size <= eden_end则将对象存放在Eden区,增加eden_top 的值,如果Eden区不足以存放,则5.
执行一次Young GC(minor collection)。
5) 经过Young GC之后,如果Eden区任然不足以存放当前对象,则直接分配到老年代。
5. java TLAB
JVM在内存新生代Eden Space中开辟了一小块线程私有的区域,称作TLAB(Thread-local allocation buffer)。默认设定为占用Eden Space的1%。在Java程序中很多对象都是小对象且用过即丢,它们不存在线程共享也适合被快速GC,所以对于小对象通常JVM会优先分配在TLAB上,并且TLAB上的分配由于是线程私有所以没有锁开销。因此在实践中分配多个小对象的效率通常比分配一个大对象的效率要高。
也就是说,Java中每个线程都会有自己的缓冲区称作TLAB(Thread-local allocation buffer),每个TLAB都只有一个线程可以操作,TLAB结合bump-the-pointer技术可以实现快速的对象分配,而不需要任何的锁进行同步,也就是说,在对象分配的时候不用锁住整个堆,而只需要在自己的缓冲区分配即可。
关于对象分配的JDK源码可以参见JVM 之 Java对象创建[初始化]中对OpenJDK源码的分析。
6. java 何时触发GC
eden或old gen空间不足时会发出minor gc或full gc。
1) new gen对象什么时候会晋升到old gen中?
1. 多次minor gc后依然存活的对象,在存活年龄超过MaxTenuringThreshold阈值时会晋升到old gen中。
2. 在创建大对象/数组时,如果设置了PretenureSizeThreshold,超过大小的对象会直接在old gen中分配内存。
2) 什么时候会出现old gen空间不足(old gen空间不足时,会触发full gc)?
1. 创建大对象,大数组时,如果设置了PretenureSizeThreshold,超过阈值会直接在old gen中分配内存,此时可能会出现old gen内存不足。
2. minor gc完成后,可能会有对象满足了MaxTenuringThreshold设置的晋升年龄,需要晋升到old gen,此时可能会出现old gen内存不足。
3. 如果设置了新生代收集担保机制即HandlePromotionFailure关闭,则会在old gen中预留edu+survivor大小的空间作为担保,如果minor gc时,
old gen无法提供足够内存进行担保,会出现old gen内存不足。
4. 调用System.gc()时,会建议jvm进行full gc,但是并不保证一定会进行,大多数情况会执行full gc。因此,要慎用System.gc(),因为full gc
比较耗时,增加full gc次数会严重影响程序执行效率。-XX:+DisableExplicitGC可以关闭System.gc()调用。
5. perm gen内存不足时,也会出发full gc。
参考:
垃圾收集算法和垃圾回收算法:
http://www.2cto.com/kf/201401/272681.html
java垃圾收集器:
http://blog.csdn.net/chjttony/article/details/7883748 (推荐)
http://www.cnblogs.com/wrencai/articles/4232264.html
内存模型:
http://www.cnblogs.com/wrencai/articles/4232264.html
java对象都是分配在堆上吗:
http://blog.hesey.net/2011/07/object-allocation-on-non-heap.html
java逃逸分析和对象内存分配,TLAB:
http://blog.csdn.net/yangzl2008/article/details/43202969
java虚拟机参数:
http://java.9sssd.com/jvm/art/432
http://www.tuicool.com/articles/RNjUfa
java垃圾回收算法和垃圾收集器的更多相关文章
- 3-JVM垃圾回收算法和垃圾收集器
垃圾回收算法和垃圾收集器 1.什么是垃圾回收 对于内存当中无用的对象进行回收,如何去判断一个对象是不是无用的对象. 引用计数法: 每个对象中都会存储一个引用计数,每增加一个引用就+1,消失一个引用就- ...
- Java虚拟机四:垃圾回收算法与垃圾收集器
在Java运行时的几个数据区域中,程序计数器,虚拟机栈,本地方法栈3个区域随着线程而生,随线程而灭,因此这几个区域的内存分配和回收具有确定性,不需要过多考虑垃圾回收问题,因为方法结束或者线程结束时,内 ...
- JVM垃圾回收算法 及 垃圾收集器
摘自<深入理解Java虚拟机> 一.什么是: GC算法是 方法论,那么垃圾收集器就是具体的 实现. 二.四种 垃圾回收算法 1.标记-清除算法:最基础的收集算法:不足有两点:1标记和清除两 ...
- 6.GC垃圾回收算法和垃圾收集器的关系
JAVAGC垃圾回收机制和常见垃圾回收算法 推荐博客:JVM垃圾回收机制和常见垃圾回收算法 JVM的内存结构.垃圾回收算法
- 《深入理解java虚拟机》笔记(5)垃圾回收算法及垃圾收集器
一.标记-清除算法 算法:分为标记和清除两个阶段,首先标记出所有需要回收的对象,再对标记对象进行回收. 不足之处:效率不高,会产生大量不连续内存碎片,导致下次分配较大内存时,若内存不足不得不触发垃圾回 ...
- Java垃圾回收之新生代垃圾收集器
问题:什么是Stop-the-World? 1.JVM由于要执行GC而停止了应用程序的执行 2.任何一种GC算法中都会发生 3.多数GC优化通过减少Stop-the-world发生的时间来提高程序的性 ...
- JVM(十),垃圾回收之新生代垃圾收集器
十.垃圾回收之新生代垃圾收集器 1.JVM的运行模式 2.Serial收集器(复制算法-单线程-Client模式) 2.ParNew收集器(复制算法-多线程-Client模式) 3.Parallel ...
- jvm(5)---垃圾回收(回收算法和垃圾收集器)
1.垃圾回收算法 1.1 标记-清除算法 算法分为“标记”和“清除”阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象.它是最基础的收集算法,效率也很高,但是会带来两个明显的问题 ...
- Java垃圾回收算法和垃圾回收器
基本上 jvm内存回收有三种 基本算法 标记-清除 标记清除的算法最简单,主要是标记出来需要回收的对象,然后然后把这些对象在内存的信息清除.如何标记需要回收的对象,在上一篇文章里面已经有说明. 标记- ...
随机推荐
- ThinkPHP 3.2 中获取所有函数方法名,以及注释,完整可运行
<?php namespace Home\Controller; use Common\Controller\BaseController; class AuthController exten ...
- 改动Dialog窗口的类名
VS2013 的MFC project(project名: MobileLink).想要改动窗口的类名时,发现不是像设置窗口名一样调用一个函数能够实现的. 实现的注意问题,请看凝视. (1) 改 ...
- webDriver API——第14部分Color Support
class selenium.webdriver.support.color.Color(red, green, blue, alpha=1) Bases: object Color conversi ...
- java阅读笔记
前言:面向对象设计的几大原则? 1>针对接口编程,而不是针对实现编程 2>优先使用对象组合,而不是类继承 1.只根据抽象类中定义的接口来操纵对象有以下两个好处? 1)客户无须知道他们使用对 ...
- [Spring MVC - 2A] - java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)
严重: Servlet.service() for servlet [springMVC] in context with path [/ExceptionManageSystem] threw ex ...
- Mybatis准备
http://www.mybatis.org/mybatis-3/zh/index.html
- oracle expdp导入时 提示“ORA-39002: 操作无效 ORA-39070: 无法打开日志文件 ”
1.导出数据库的时候报错 expdp zz/zz@orcl directory=exp_dp dumpfile=zz_20170520.dump logfile=zz_20170520.log 2 ...
- Archive将多个对象归档到同一个文件
使用archiveRootObject:toFile:方法能够将一个对象直接写入到一个文件里.但有时候可能想将多个对象写入到同一个文件里,那么就要使用NSData来进行归档对象. NSData能够为一 ...
- Xcode中利用git源代码版本号控制
git是一个版本号控制系统,能够通过命令行来调用,也有专门的桌面软件.这里主要介绍在Xcode中怎样利用git来进行版本号的控制. 一.创建git源 从Xcode5開始引入了使用git的一些新特性.将 ...
- 用js来传参到父网页实现
今天搞了半天,用location.href提交参数到后台,结果php无法接收到参数,这让我找了半天,终于发现原因是本页被另外的主页引用了,最终发现问题出在提交js上,最终用parent.locatio ...