GC垃圾回收器
java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”。jvm解决的两个问题:给对象分配内存以及回收分配给对象的内存。GC:将内存中不再被使用的对象进行回收。GC的作用域是JVM运行时数据区的方法区和堆。频繁收集Young区;较少收集Old区;基本不动Perm区。
1.概述
垃圾收集(GC)需要完成的3件事:
(1)哪些内存需要回收?
(2)什么时候回收?
(3)如何回收?
GC类型:
(1) Minor GC:针对新生代的GC
(2) Major GC:针对旧生代的GC
(3) Full GC:针对永久代、新生代、旧生代三者的GC
为什么需要了解GC和内存分配?
当需要排查各种内存溢出、内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,就需要对这些“自动化”的技术实施必要的监控和调节。
在java内存运行时区域的各个部分中,程序计数器、虚拟机栈、本地方法栈3个区域随线程而生,随线程而灭,栈中的栈帧随着方法的进入和退出而有条不紊的执行着出栈和入栈操作。每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知的,因此这几部分区域的内存分配和回收都具有确定性,不需要考虑回收的问题,因为方法结束或者线程结束时,内存自然就跟着回收了。而java堆和方法区则不一样,一个接口中的多个实现类需要的内存可能不一样,一个方法中的多个分支需要的内存也可能不一样。只有在程序处于运行期时才能知道会创建哪些对象,这部分内存的分配和回收都是动态的,垃圾收集器所关注的就是这部分内存。
2.判断对象是否已死
(1) 引用计数法
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。主流的java虚拟机里面没有选用引用计数算法来管理内存,其中最主要的原因就是它很难解决对象之间相互循环引用的问题。
(2) 可达性分析算法
算法的基本思想就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。
在java语言中,可作为GC Roots的对象包括下面几种:
a.虚拟机栈(栈帧中的本地变量表)中的引用的对象
b.方法区中类静态属性引用的对象
c.方法区中常量引用的对象
d.本地方法栈中JNI(Native方法)引用的对象
判断一个类是否是“无用的类”的条件为:
a. 该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例
b. 加载该类的ClassLoader已经被回收
c. 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
3. 垃圾收集算法
(1) 标记--清除
标记清除算法是最基础的算法,算法分为“标记”和“清除”两个阶段,首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
不足:一个是效率问题,标记和清除两个过程两个过程效率都不高;另一个是空间问题,标记清除之后会产生大量的不连续的内存碎片,空间碎片太多可能导致之后需要分配大量内存对象时,无法找到足够的连续的内存而不得不提前触发另一次垃圾收集动作。


(2) 复制算法
将可用内存按容量划分为大小相等的两块,每次只使用其中的一块,当一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂的情况了,实现简单,运行高效,代价为将内存缩小为原来的一半。这种方法适用于回收新生代。

(3) 标记--整理算法
标记整理算法中的标记过程与标记清除算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。

(4) 分代收集算法
在新生代中,每次垃圾收集时都发现大批对象死去,只有少量存活,选择复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就需要使用标记清理或者标记整理的算法来回收。
4.垃圾收集器
如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。
(1) Serial收集器
它的“单线程”的意义并不仅仅说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是在它进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束。适用于新生代。
(2) ParNew收集器
ParNew收集器就是Serial收集器的多线程版本。
(3) Parallel Scavenger收集器
Parallel Scavenger收集器是一个新生代收集器,它也是使用复制算法的收集器,又是并行的多线程收集器。
(4) Serial Old收集器
Serial Old收集器是Serial收集器的老年代版本,它同样是一个单线程收集器,使用“标记清理”算法。
(5) Parallel Old 收集器
Parallel Old 是 Parallel Scavenger收集器的老年代版本,使用多线程和“标记整理”算法。
(6) CMS 收集器
CMS收集器是一种以获取最短回收停顿时间为目标的收集器。基于“标记清除”算法实现的。整个步骤分为:
a. 初始标记
b. 并发标记
c. 重新标记
d. 并发清除
(7) G1收集器
优点:并行和并发,分代收集,空间整合,可预测停顿。
5. 内存分配
(1) 对象优先在Eden分配
大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC。
(2) 大对象直接进入老年代
大对象是指需要连续内存空间的java对象,最典型的大对象就是很长的字符串以及数组。经常出现大对象容易导致内存还有不少空间时就提前触发垃圾收集以获取足够的连续空间来“安置”它们。
(3) 长期存活的对象将进入老年代
虚拟机为每一个对象定义一个对象年龄计数器,如果对象在Eden出生并经过第一次Minor GC后仍然存活,并且被Survivor容纳的话,将被移动到Survivor空间中,并设置对象年龄为1.当年龄增加到一定程度(默认为15岁),就会被晋升到老年代。
(4) 动态对象年龄判定
如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或者等于该年龄的对象就可以直接进入老年代,无须等到阈值年龄。
(5) 空间分配担保
6. 内存分析工具
(1) Jmc
java 7u40发布中加入的性能监控工具。功能全面,包括CPU占用率、内存使用情况、I/O耗时等。常用于性能分析。
(2) Jconsole
jdk自带的可视化监视和管理控制台。监控某个进程的内存、线程、类等信息。可观察堆内存新生代、老年代的使用情况。
(3) Jvisualvm
jdk自带的可远程或本地监控内存泄漏,跟踪垃圾回收的工具。可以dump堆内存数据
(4) Eclipse Memory Analyzer
是分析堆数据的专业工具,可以定位内存泄漏的原因。
GC垃圾回收器的更多相关文章
- [Java基础]-- Java GC 垃圾回收器的分类和优缺点
https://blog.csdn.net/high2011/article/details/80177473?utm_source=blogxgwz2 参考:elasticsearch实战-使用G1 ...
- 一篇文章让你了解GC垃圾回收器
简单了解GC垃圾回收器 了解GC之前我们首先要了解GC是要做什么的?顾名思义回收垃圾,什么是垃圾呢? GC回收的垃圾主要指的是回收堆内存中的垃圾对象. 从根对象出发,所有被引用的对象,都是存活对象 其 ...
- .NET GC垃圾回收器
GC垃圾回收器简介 全名: Garbage Collector 原理: 以应用程序的根(root)为基础,遍历应用程序堆(heap)上动态分配的所有对象,通过识别它们是否被引用来确定哪些对象是已经死亡 ...
- 如何获取GC(垃圾回收器)的STW(暂停)时间?
前言 在现代的容器化和微服务应用中,因为分布式的环境和错综复杂的调用关系,APM(Application Performance Monitoring 应用性能监控)显得尤为重要,它通过采集应用程序各 ...
- GC(垃圾回收器)中的算法
GC的两种判定方法 (1) 引用计数法 给对象添加一个引用计数器,每当引用一次+1,每次失效时-1,当计数器为0时,表示对象就是不可能再被使用的. (2) 可达性分析算法 将“GC Roots”对象作 ...
- Java虚拟机笔记(二):GC垃圾回收和对象的引用
为什么要了解GC 我们都知道Java开发者在开发过程中是不需要关心对象的回收的,因为Java虚拟机的原因,它会自动回收那些失效的垃圾对象.那我们为什么还要去了解GC和内存分配呢? 答案很简单:当我们需 ...
- Android内存优化5 了解java GC 垃圾回收机制3
引言 接App优化之内存优化(序), 作为App优化系列中内存优化的一个小部分. 由于内存相关知识比较生涩, 内存优化中使用到的相关工具, 也有很多专有名词. 对Java内存管理, GC, Andro ...
- 牛客网Java刷题知识点之垃圾回收算法过程、哪些内存需要回收、被标记需要清除对象的自我救赎、对象将根据存活的时间被分为:年轻代、年老代(Old Generation)、永久代、垃圾回收器的分类
不多说,直接上干货! 首先,大家要搞清楚,java里的内存是怎么分配的.详细见 牛客网Java刷题知识点之内存的划分(寄存器.本地方法区.方法区.栈内存和堆内存) 哪些内存需要回收 其实,一般是对堆内 ...
- C#.Net GC(garbage Collector) 垃圾回收器
以前一直以为gc的原理很简单,也就是分代处理堆数据,直到我的膝盖中了一箭(好吧 直到有天汪涛和我说他面试携程的面试题 关于服务器和 工作站gc 的区别)其实我当时尚不知道 工作站和服务器有什么区别更不 ...
随机推荐
- golang 使用pprof和go-torch做性能分析
软件开发过程中,项目上线并不是终点.上线后,还要对程序的取样分析运行情况,并重构现有的功能,让程序执行更高效更稳写. golang的工具包内自带pprof功能,使找出程序中占内存和CPU较多的部分功能 ...
- 画图必备numpy函数
给定一堆数字,需要统计这些数字中每个数字的个数. 如果这些数字是整数,那自然可以精确统计出来. 如果这些数字是浮点数,如果精确统计会发现几乎每个数字都只出现了一次.所以浮点数就要通过区间的方式进行统计 ...
- int转换char的正确姿势
一:背景 在一个项目中,我需要修改一个全部由数字(0~9)组成的字符串的特定位置的特定数字,我采用的方式是先将字符串转换成字符数组,然后利用数组的位置来修改对应位置的值.代码开发完成之后,发现有乱码出 ...
- Unity应用架构设计(2)——使用中介者模式解耦ViewModel之间通信
当你开发一个客户端应用程序的时候,往往一个单页会包含很多子模块,在不同的平台下,这些子模块又被叫成子View(视图),或者子Component(组件).越是复杂的页面,被切割出来的子模块就越多,子模块 ...
- Mybatis抛出:Cannot obtain primary key information from the database, generated objects may be incomplete
使用 mybatis generator 生成pojo.dao.mapper时,可能会遇到 Cannot obtain primary key information from the databas ...
- 微信小程序--data的赋值与取值
通过小程序官方文档可知:Page() 函数用来注册一个页面.接受一个 object 参数,其指定页面的初始数据.生命周期函数.事件处理函数等.其中的参数data用来设置初始数据,WXML 中的动态数据 ...
- MySql基本查询、连接查询、子查询、正则表达查询解说
林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 查询数据指从数据库中获取所须要的数据.查询数据是数据库操作中最经常使用,也是最重要的操作.用户 ...
- mysql知识汇总
一.数据类型介绍 数据类型 字节长度 范围或用法 bigint 8 无符号[0,2^64-1],有符号[-2^63 ,2^63 -1] binary(M) M 类似Char的二进制存储,只包含byte ...
- dockerd启动配置_修改IP和systemd管理
docker采用CS架构,dockerd是管理后台进程,默认的配置文件为/etc/docker/daemon.json(--config-file可以指定非默认位置). 一个完整的daemon.jso ...
- ant 通配符
ant 通配符 我们常用的匹配模式有ANT模式,比如acegi可以用PATTERN_TYPE_APACHE_ANT来使用ANT匹配模式,那什么是ANT匹配模式呢. ANT通配符有三种: 通 ...