Java的垃圾回收和内存分配策略
本文是《深入理解Java虚拟机 JVM高级特性与最佳实践》的读书笔记
在介绍Java的垃圾回收方法之前,我们先来了解一下Java虚拟机在执行Java程序的过程中把它管理的内存划分为若干个不同的的数据区的什么?
1.Java运行时数据区的划分
如下图:

其中程序计数器,虚拟机栈,本地方法栈这3个区域的内存随线程而生,随线程而灭的,因此这几个区域的内存分配与回收都是有确定的,我们不需要考虑这几个区域的内存的分配与回收。而堆和方法区则不一样,我们只有在程序处于运行期间时才能知道会创建哪些对象,这部分的内存的分配和回收都是动态的,垃圾收集器关注的就是这部分内存(堆和方法区)。
下面我们先简单介绍一下这几部分区域存放的什么东西;
- 程序计数器:(线程私有)当前线程所执行的字节码的行号指示器,解释器工作时就是通过改变这个计数器的值来取得下一条需要执行的指令。
- Java虚拟机栈:(线程私有)描述的是Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每个方法从刻调用直到执行完成,就对应于栈帧在虚拟机栈中的入栈和出栈的过程。我们常说的栈内存就是这个。
- 本地方法栈:(线程私有)与Java虚拟机栈类似,只不过这是为虚拟机会用到的Native方法服务的,它也会抛出StackOverflowError和OutOfMemoryError异常。
- Java堆:(所有线程共享)几乎所有的对象实例都会在这里分配内存,Java堆还可以细分为新生代和老年代;
- 方法区:(线程共享)用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据;(在某些虚拟机上也称为永久代)。
2 Java(JVM)的垃圾回收机制
2.1 哪些内存需要回收?
在Java中,都是通过可达性分析来对象是否存活的(如果对象是死的,那么它所占用的内存就是需要回收的)。可达性分析算法的基本思想就是通过一系列被称为“GC Roots”的对象开始,从这些节点向下搜索,搜索走过的路线称为引用链。当一个对象没有在任何引用链上出现,则这个对象会被判定为不可用的(死的,可回收的)。
在被可达性分析算法判定为不可用的对象,也并非是一定就是会被回收的,它们还会经历一次筛选的过程,筛选的条件就是此对象是不是要执行finalize()方法,如果对象没有覆盖finalize()方法或它的finalize()方法在上一次垃圾回收器工作时已经执行过了,则被判定为不用执行finalize()方法(对象会在这次回收中被回收),若判定为需要执行finalize()方法,则这个对象会被放置在一个F-Queue队列中,稍后虚拟机会建立一个finalizer线程(低优先级)来触发这个方法,但虚拟机不承诺会等它执行完这个方法。(也就是这个对象可能在执行finalize()方法时被回收了),如果在finalize()方法中,对象加入了任何一个引用链中,则这个对象在这次回收器工作时就不会被回收了。
在Java中,有几种可作为GC Roots对象:虚拟机栈(栈帧中的本地变量表)中引用对象。方法区中类静态属性和常量引用的对象和本地方法栈中JNI引用的对象;
2.2 垃圾回收算法
2.2.1 标记-清除(Mark-Sweep)算法
首先会利用前面的可达性分析算法标记出需要回收的对象,在标记完成后就统一回收所有被标记的对象,这个算法的缺点主要有:
- 效率问题,在标记和清除两个过程中效率都不高;
- 空间问题,标记清除之后会产生大量的内存碎片,碎片太多,可能导致在下次为大对象分配内存时,提前触发一次垃圾回收动作;
2.2.2 复制算法(Coping)
将可用的内存分为两块,每次只使用其中的一块,这样每次只需要顺序分配内存就可以,当一块的内存用完后,就把还存活的对象复制到另一块内存中去,然后对使用过的内存空间进行回收就可以了。(一般不会采用平均分成两块的方式,现代虚拟机一般会将内存分成一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden空间和一块Survivor空间,回收时,将Eden空间和Survivors空间里还存活的对象复制到另一块没有使用的Survivor空间中,然后清理掉用过的空间),一般会这种算法回收新生代的内存空间;
2.2.3 标记-整理(Mark-Compact)算法
先利用可达性分析算法标记需要回收的对象,然后就让还存活的对象(出现在任何引用链中的对象)都向一端移动,然后清理掉端边界外的内存。(一般用来回收老年代的对象);
3 什么时候回收
大多数情况下,对象优先在Eden区中分配(大对象直接在老年代分配),当Eden没有足够空间时,JVM就会发起一次Minor GC。在进行Minor GC 之前,JVM会检查老年代最大可用的空间是否大于新生代所有对象的空间,如果成立,则Minor GC是安全的,否则,JVM就会去检查HandlePromotionFailure设置值是否允许担保失败。如果允许担保失败,则会继续检查老年代最大可用空间是否大于历次晋升到老年代对象的平均大小,如果是,则会尝试进行Minor GC(若失败,就会进行一次Full GC);否则就会改为进行一次Full GC;
Java的垃圾回收和内存分配策略的更多相关文章
- 【java虚拟机序列】java中的垃圾回收与内存分配策略
在[java虚拟机系列]java虚拟机系列之JVM总述中我们已经详细讲解过java中的内存模型,了解了关于JVM中内存管理的基本知识,接下来本博客将带领大家了解java中的垃圾回收与内存分配策略. 垃 ...
- Java虚拟机垃圾回收:内存分配与回收策略 方法区垃圾回收 以及 JVM垃圾回收的调优方法
在<Java对象在Java虚拟机中的创建过程>了解到对象创建的内存分配,在<Java内存区域 JVM运行时数据区>中了解到各数据区有些什么特点.以及相关参数的调整,在<J ...
- java 垃圾回收及内存分配策略
一.在垃圾收集器对堆进行回收前,首先需要判断对象是否"存活",对已经"死去"的对象进行回收 判断对象是否存活:引用计数法和可达性分析法 引用计数法:给对象添加一 ...
- Java GC 垃圾回收算法 内存分配
垃圾回收(Garbage Collection, GC)是Java不同于c与c++的重要特性之一. 他帮助Java自动清空堆中不再使用的对象. 由于不需要手动释放内存,程序员在编程中也可以减少犯错的机 ...
- [jvm]垃圾回收与内存分配策略
一.垃圾回收算法 概述 JVM中,当创建的对象不再被使用的时候,此时我们认为他是无用的“垃圾”:在现代主流的商用jvm中,都是通过可达性分析来判断对象是否存活的.这个算法的基本思想是通过一系列“GCR ...
- Java虚拟机----垃圾回收与内存分配
一.垃圾回收的对象: 在Java的运行时数据区中,程序计数器和虚拟机栈.本地方法栈是随着线程的生灭而生灭,栈当中栈帧的大小在编译的时候已知,在方法结束之后栈帧出栈,这部分的垃圾回收是明确的,因此需要讨 ...
- Java虚拟机垃圾收集器与内存分配策略
Java虚拟机垃圾收集器与内存分配策略 概述 那些内存须要回收,什么时候回收.怎样回收是GC须要完毕的3件事情. 程序计数器.虚拟机栈与本地方法栈这三个区域都是线程私有的,内存的分配与回收都具有确定性 ...
- JVM学习02:GC垃圾回收和内存分配
JVM学习02:GC垃圾回收和内存分配 写在前面:本系列分享主要参考资料是 周志明老师的<深入理解Java虚拟机>第二版. GC垃圾回收和内存分配知识要点Xmind梳理 案例分析1-(G ...
- NET的堆和栈04,对托管和非托管资源的垃圾回收以及内存分配
在" .NET的堆和栈01,基本概念.值类型内存分配"中,了解了"堆"和"栈"的基本概念,以及值类型的内存分配.我们知道:当执行一个方法的时 ...
随机推荐
- LCX端口转发实现内网突破
工具:lcx.exe 原理:当目标主机仅开放了web服务,而该服务又仅能供内网用户使用,外网用户根本无法直接访问.因此想要让外网用户能能够访问局域网中的系统服务,必须进行端口映射等操作才行.其原理就是 ...
- Gearman使用示例
最近的一个旧项目重构过程中,使用到了gearman这个开源项目,简单来讲,这是一个类似MQ的异步系统,一边派发任务,一边处理任务(有类似MQ中的消息发送方与接收方),目前支持java,php等多种语言 ...
- Android开发之带你轻松集成友盟统计
友盟统计是什么呢?为什么要集成他呢? 当我们需要获取自己写的软件的装机量和用户使用信息时,这时我们可以集成友盟统计. 首先到友盟统计中注册账号什么的就不废话了,直接看创建项目: 在个人中心中的管理里面 ...
- 记录PHP的超全局变量$_SERVER
$_SERVER是PHP中十分实用的超全局变量,在开发可移植的网站的时候会变得很有用. 下面我记录一下我自己常用到的几个变量 1.$_SERVER['SERVER_NAME']:记录了网站的域名. 2 ...
- BZOJ 3931: [CQOI2015]网络吞吐量
3931: [CQOI2015]网络吞吐量 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1555 Solved: 637[Submit][Stat ...
- 【BZOJ-3143】游走 高斯消元 + 概率期望
3143: [Hnoi2013]游走 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2264 Solved: 987[Submit][Status] ...
- MVC 总结
以下内容摘自 PHP for Absolute Beginners, Thomas Blom Hansen & Jason Lengstorf The model-view-controlle ...
- oracle--逻辑对象--bai
1 序列 sequence oracle特有.实现"自增"或"自减"的逻辑对象. 2 同义词 synonym 对表取别名,该别名被永久存储. 比视图更省资源. ...
- CSS style和HTML style有什么区别?
https://zhidao.baidu.com/question/1238362131134658699.html 没有什么区别啊,都是样式的意思. 没有分别的!CSS提高代码重用性,加速浏览器下载 ...
- postman 测试API - token
1.使用全局变量保存token 2.再调用 参考文章 http://www.jianshu.com/p/13c8017bb5c8 https://testerhome.com/topics/6555