JAVA内存模型及垃圾回收自我总结
本文为原创,根据《深入理解java虚拟机》和自己的一些理解进行整理,单纯和看其他人的博客感觉不如自己一点点的画和记录来的印象深刻。
JAVA内存模型:

上图中:局部变量表所需的内存在编译期已经分配完成 表达有误, 准确的表达应该是:局部变量表所需的内存在编译期就已经计算完成(即需要在运行时分配多大内存)。

判断对象是否已死(可以回收)的算法

从永久代到年轻代的引用可以被当成 GC roots,从年轻代到永久代的引用在标记阶段被直接忽略掉
方法区(永久代)回收的相关说明:
永久代的垃圾回收主要两部分内容:废弃的常量和无用的类。 废弃的常量:无任何对象引用此常量。 无用的类:、该类所有实例已经被回收(堆中不存在该类的任何实例)。
、加载该类的ClassLoader已经被回收。
、给类对应的Class对象没有任何地方呗引用,无法在任何地方通过反射访问该类的方法
垃圾收集的算法:
1、标记 - 清除算法
包含标记和清除2个阶段,是最基础的算法。标记就是标记出那些已经可以被回收的对象,在标记完成后进行清楚,此算法效率不高而且会产生内存碎片,当程序在以后的运行中需要分配一块大的连续的内存时可能因为内存碎片的问题而提前触发再次垃圾回收。
过程示意图如下:

2、复制算法(新生代采用的算法之一)
为了解决标记-清除 算法 的效率问题的,将内存划为多块,在标记完一块区域的对象的存活状态后,将存活的对象拷贝到另外一块上,然后将之前的那块一次清理掉。
在新生代上对象存活期很短,并且98%的对象是朝生夕死,所以在内存的划块上不需要1:1进行划分,hotspot虚拟机默认按照Eden-80%,两块Survivor各10%进行划分(8:1),其中Eden和一块Survivor空间用来存放新生代的对象,还有一块用来复制垃圾回收时Eden和另外一块Survivor的存活对象,然后一次清除调用Eden和那块Survivor内存,下次垃圾回收时这2块Survivor的功能互相调换。当一块Survivor不够装下存活的对象时,则会向老年代的分配担保机制(借内存)进入到老年代。
复制算法的示意图:

3、标记 - 整理算法
相比标记-清理算法,此算法解决了标记-清理算法的内存碎片问题,清理完可回收的对象后会对该内存块进行整理。
算法示意图:

4、分代收集算法
当前商业虚拟机都采用此算法,其实说这是算法还不如说是一个将前面3个算法在新生代和老年代上应用不同算法的一个策略,新生代采用复制算法,老年代采用“标记-清除”或者“标记-整理”算法。
垃圾回收器(垃圾收集算法的具体实现)
HotSpot 1.6版Update22的收集器入下所示:

上面部分是新生代的垃圾回收器,下面部分是老年代的垃圾回收器,中间的连线表示这2个回收器可以配合一起使用。
新生代的垃圾收集器
1、Serial收集器(复制算法)
此收集器是最基本的,也是历史最悠久的收集器,是JDK1.3.1之前新生代的唯一选择,该收集器的缺点是垃圾收集器回暂停用户的所有线程来进行单线程的垃圾收集,后面的其它收集器基本就是在此收集器的基础进行优化修改而来,在Client模式下运行还是可以的接受的。
运行示意图如下:

2、ParNew收集器(复制算法)
Serial的多线程版本,是许多运行在Server模式下的虚拟机中新生代收集器的首选。在多核心的服务器上运行优势明显,默认开启的线程=CPU核心数,
通过使用-XX:ParallelGCThreads参数可以来限制垃圾收集的线程数。
运行示意图:

3、Parallel Scavenge收集器(复制算法)
跟parNew收集器差不多,但与上面2个收集器的关注点不同,前面的2个更多的关注用户的停顿时间,而此收集器更关注CPU的吞吐量(吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)),
其中有2个参数可以控制这个吞吐量,1、-XX:MaxGCPauseMillis xxxx,控制最大垃圾收集停顿时间(x>0的毫秒数)。2、-XX:GCTimeRatio XXX,设置吞吐量大小(设置一个0<x<100的整数,表示垃圾收集器时间占总时间的比率,相当于吞吐量的倒数)。
另外,此收集器还有一个参数-XX:+UseAdaptiveSizePolicy,如果打开这个开发,则新生代的大小(-Xmn)、Eden、Survivor(-XX:SurvivorRatio)、晋升老年代的对象年龄(-XX:PretenureSizeThreshold)等参数就不需要手工指定了,虚拟机会根据系统的运行情况来动态调整。
运行示意图:

老年代收集器
1、Serial Old收集器(标记-整理算法)
新生代serial的老年代版本,主要有如下2个用途:1、在JDK1.5以及之前的版本搭配新生代的Parallel Scavenge收集器使用。2、作为CMS收集器发生Concurrent Mode Failure的一个后备方案。
2、Parallel Old收集器(标记-整理算法)
新生代Parallel Scavenge收集器的老年代版本,在JDK1.6的版本中才提供,只能和新生代的Parallel Scavenge收集器搭配使用。
3、CMS收集器(标记-清除算法)
Concurrent Mark Sweep,一种以获取最短回收停顿时间为目标的收集器,具有并发低顿挫的特点,但其也有几个缺点:
①对CPU资源很敏感(需要跟用户线程并发执行)。
②无法处理浮动垃圾(Floating Garbage,在标记过程后产生的垃圾),CMS需要预留足够的内存空间给用户线程使用,所以CMS收集器在老年代使用了68%的空间后被激活(可以通过-XX:CMSInitiatingOccupancyFranction参数来配置触发百分比),如果在运行过程中预留的内存无法满足程序需要,则会出现一次“Concurrent Mode Failure”失败并启用后备预案(Serial Old收集器)进行Full GC。
③由于采用标记-清除算法,会产生内存碎片,不过可以配置-XX:+UseCMSCompactAtFullCollection开关让Full GC后进行一次碎片整理,也可以使用-XX:CMSFullGCsBeforeCompaction来设置执行多少次Full GC自动来一次碎片整理。
共分为4个过程:
㈠、初始标记
需要暂停用户线程,但过程很快。
㈡、并发标记
㈢、重新标记
需要暂停用户线程,对前面的标记进行修正。
㈣、并发清除
运行示意图:

4、G1收集器
Garbage First收集器是当前收集器技术发展的前沿成果,在JDK1.6_update14提供试用,是一款面向服务器应用的垃圾收集器。
主要有如下特点:
● 并发运行
● 基于标记-整理算法,不会产生空间碎片
● 非常精确的控制停顿,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在收集上的时间不超过N毫秒,这几乎是实时JAVA(RTSJ)垃圾收集器的特征了
● 将整个堆(新生代、老年代)划分为多个大小固定的独立区域,并与这些区域为单位进行垃圾回收,避免对整个堆进行全量回收操作,并对这些区域进行优先级维护和回收。
进入老年代的几种途径
1、在新生代GC过程中survivor空间不够,通过老年代的分配担保机制提前转入老年代。
2、超过参数PretenureSizThreshold设置的值的大对象直接进入老年代,所谓大对象就是需要大量连续内存空间的java对象(例如很长的字符串和大数组)。
3、长期存活的新生代对象进入老年代,如果对象在一次Minor GC(新生代GC)后仍存活并且能被survivor容纳后被移动到Survivor中后将该对象的年龄+1,当它的年龄达到一定程 度(默认15)后就会晋升到老年代,这个阀值可以通过-XX:MaxTenuringThreshold来设置。
4、虚拟机并不总要求对象达到XX:MaxTenuringThreshold的值后才晋升老年代,如果在Survivor空间中相同年龄所有对象大小总和大于Survivor空间的一半,年龄大于或者等于 该年龄的对象就可以直接进入老年代。
JAVA内存模型及垃圾回收自我总结的更多相关文章
- Java内存模型与垃圾回收
1.Java内存模型 Java虚拟机在执行程序时把它管理的内存分为若干数据区域,这些数据区域分布情况如下图所示: 程序计数器:一块较小内存区域,指向当前所执行的字节码.如果线程正在执行一个Java方法 ...
- java内存模型和垃圾回收(收藏)
java内存模型: https://www.cnblogs.com/handsomeye/p/5442879.html java垃圾回收 http://www.cnblogs.com/handsome ...
- Java内存模型与垃圾回收笔记
内存模型 栈. 局部变量(基本类型)与对象引用:线程隔离.每个方法执行时会创建一个栈帧,存储局部变量等. 堆. 对象实例:线程共享. 方法区.类信息.常量(final).静态变量.符号引用: 线程共享 ...
- java内存模型和垃圾回收
摘抄并用于自查 JVM内存模型 1. Java程序具体执行的过程: Java源代码文件(.java后缀)会被Java编译器编译为字节码文件(.class后缀) 由JVM中的类加载器加载各个类的字节码文 ...
- Java虚拟机内存模型及垃圾回收监控调优
Java虚拟机内存模型及垃圾回收监控调优 如果你想理解Java垃圾回收如果工作,那么理解JVM的内存模型就显的非常重要.今天我们就来看看JVM内存的各不同部分及如果监控和实现垃圾回收调优. JVM内存 ...
- 【Java_基础】JVM内存模型与垃圾回收机制
1. JVM内存模型 Java虚拟机在程序执行过程会把jvm的内存分为若干个不同的数据区域来管理,这些区域有自己的用途,以及创建和销毁时间. JVM内存模型如下图所示 1.1 程序计数器 程序计数器( ...
- 程序猿的日常——JVM内存模型与垃圾回收
Java开发有个很基础的问题,虽然我们平时接触的不多,但是了解它却成为Java开发的必备基础--这就是JVM.在C++中我们需要手动申请内存然后释放内存,否则就会出现对象已经不再使用内存却仍被占用的情 ...
- JVM内存模型和垃圾回收
Java开发有个很基础的问题,虽然我们平时接触的不多,但是了解它却成为Java开发的必备基础——这就是JVM.在C++中我们需要手动申请内存然后释放内存,否则就会出现对象已经不再使用内存却仍被占用的情 ...
- (转载)JVM中的内存模型与垃圾回收
转载自微信公众号:Java高级架构(Java-jiagou)-----看完这篇文章,我奶奶都知道JVM中的内存模型与垃圾回收了! 六.内存模型 6.1 内存模型与运行时数据区 Java虚拟机在执行J ...
随机推荐
- [转]PHP SOCKET编程
FROM : http://blog.csdn.net/hguisu/article/details/7448528 1. 预备知识 一直以来很少看到有多少人使用php的socket模块来做一些事情, ...
- [转]XCache 3.0.0 发布,PHP 性能提升方案
From : http://www.oschina.net/news/34304/xcache-3-0-0 XCache 3.0.0 发布,该版本除了 bug 修复,对 XCache 管理页面做了很多 ...
- chrome DevTools之黑箱大法(Blackbox ) 黑箱化源代码
Blackbox 提高JavaScript调试效率 所有人前端开发人员都会遇到的问题,您的应用程序代码中会出现错误.您开始调试,但是逐行执行代码时,调试器有时会跳转到不是您的焦点的源文件(例如第三方J ...
- verilog语法实例学习(8)
常用的时序电路介绍 在电平敏感的锁存器时钟信号有效期(高电平)期间,锁存器的状态随着输入信号的变化而变化.有时候,我们需要存储器的状态在一个时钟周期只改变一次,这个时候就用到了触发器.触发器(flip ...
- Pascal's Triangle II Leetcode java
题目: Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3, Return ...
- 设置让php能够以root权限来执行exec() 或者 shell_exec()
一.查看启动你php的进程的用户是谁. 可以通过在命令行执行:ps -ef | grep php来看.或者在php中执行 echo exec('whoami') 来查看.centos下默认会是nobo ...
- 解决eclipse导出javadoc时的“错误: 编码GBK的不可映射字符”问题(转)
http://blog.csdn.net/psy1100/article/details/51179342 今天要将自己的API接口和MODEL导出来一份java doc参考文档, 但是在导出的时候却 ...
- Kafka:ZK+Kafka+Spark Streaming集群环境搭建(五)针对hadoop2.9.0启动之后发现slave上正常启动了DataNode,DataManager,但是过了几秒后发现DataNode被关闭
启动之后发现slave上正常启动了DataNode,DataManager,但是过了几秒后发现DataNode被关闭 以slave1上错误日期为例查看错误信息: /logs/hadoop-spark- ...
- Spring(十九):Spring AOP(三):切面的优先级、重复使用切入点表达式
背景: 1)指定切面优先级示例:有的时候需要对一个方法指定多个切面,而这多个切面有时又需要按照不同顺序执行,因此,切面执行优先级别指定功能就变得很实用. 2)重复使用切入点表达式:上一篇文章中,定义前 ...
- [Angular] Communicate with Angular Elements using Inputs and Events
In a real world scenario we obviously need to be able to communicate with an Angular Element embedde ...