文档章节

jvm的内存回收和垃圾回收器

qingfeng哥
 qingfeng哥
发布于 2014/06/05 11:53
字数 2065
阅读 407
收藏 9

jvm的内存回收和垃圾收集器

1、为什么要垃圾回收器

内存很宝贵,有限

内存泄露:该释放的内存没有而且永远没机会被释放,导致内存耗尽

内存溢出:分配不到内存了

C++中内存分配和释放完全自主,但智者千虑必有一种内存泄露的可能
要是有自动的、动态的内存分配的语言就好了,
既然能自动分配内存,那就必须得有配套的能自动回收(释放)这些内存 的机制

早在java之前就有语言能自动分配内存和自动回收内存(如Lisp),相比内存自动分配,内存自动回收更为重要和关键,因为内存是很宝贵的有限资源,这是个很高深的研究课题,主要有三个疑问:
    哪些内存需要回收           什么时候回收(释放)             怎么回收 

这些需要释放回收的内存也换个叫法就是 内存垃圾
于是解答上述问题就产生了各式垃圾回收器garbage collect-GC

jvm采用自动内存管理,并屏蔽指针这个反人类的东西,让很多人喜欢上java

2、了解jvm的内存布局

线程私有:jvm栈stack(该栈中push和pop的是带有复杂数据的栈帧)、
              pc计数器(指明正在执行哪条指令了)、
              本地方法栈
              这三个区的内存 随着线程的生灭而分配和释放,
              他们
需要的内存大小在类结构确定后、编译期就可以基本确定,gc基本不管这块

线程共享:堆heap和方法区method area(含有运行时常量区)
              堆中有多少对象非得跑起来才能确定的
              方法区中的类结构信息等数据是动态加载进来的
              都是不确定的内存分配,这两块才是GC的主战场

有了内存布局的宏观认识,我们需要知道

3、怎么限制各个区的大小

即jvm运行参数,以下参数是hotspot的参数,和怎样人为来产生溢出

1、heap内存大小:-Xms20M -Xmx20M -XX:+HeapDumpOnOutOfMemoryError
                          最小        最大                oom时dump溢出时内存堆转储快照

溢出方法:不断的生成对象的实例,且不置为null

2、方法区内存大小:-XX:PermSize=20M -XX:MaxPermSize=30M

溢出方法:不断的通过反射生成新的类

3、jvm栈和本地方法栈的大小:-Xss30M -Xoss10M

溢出方法:方法递归不返回,大量线程

4、直接内存大小:-XX:MaxDirectMemorySize=20M  如果没设置的话则默认与heap堆的最大值一样(-Xmx)

溢出方法:反射获取Unsafe类的实例,然后不停的分配内存allocateMemory()

好了,针对堆和方法区,回到垃圾回收器要解决的三个问题:

4、哪些内存需要回收---对象的死活

经典引用计数法:给对象配个引用计数器,每次引用就+1,引用失效时-1 计数为0时,表明对象不再被使用
jvm没有采用引用计数器算法,因为 有对象间互相循环引用导致无法释放的问题(php、python)

jvm采用根搜索算法-对象引用遍历法           GC Roots Tracing

基本思路:采用图论知识
从一系列名为 GC Roots的对象节点出发,向下搜索,搜索走过的路径为引用链,如果一个对象和根root之间没有任何引用链可通(不可达),则认为该对象没有用了,可以死去,被标记为可回收对象

可以作为GC Roots的对象:
    栈帧中的引用的对象
    方法区中:类静态属性引用的对象、常量引用的对象
   本地方法栈中:JNI的引用的对象

?怎么回收

5、垃圾回收算法

明确 所有垃圾回收时刻都会发生  全停顿 stop the world, 应该尽量减短这个时间

产生了那么多死对象,得想办法回收他们,再入轮回。怎么个做法?基本的思路有四种:

1、标记-清理(mark-sweep)算法:两阶段,第一遍扫描标记哪些对象已死,第二遍扫描清除标死的对象

缺点:两次遍历效率不高,清除后内存产生不连续的碎片

2、复制算法copying:将内存均分,每次在其中一块分配对象,快用完时将还活着的对象都复制到 另一块上,清空已使用的那块即可。代价是内存减半,一点优化是不均分

3、标记-整理(mark-compact)算法,这是标记-清理法的改进,一遍标记并将活的对象移到内存区的一端,然后清理边界外的死对象即可


GC假设

大多数对象会很快变得不可达
只有很少的由老对象(创建时间较长的对象)指向新生对象的引用


由上述对象死活判断依据、GC假设、加上统计数据的发现,可以将对象分为不同的generation

6、JVM分代内存回收

回收之前先了解内存的分配规则,之前我去了解了下Node.js的v8 js引擎的垃圾回收机制 发现这些虚拟机都采用相类似的方法和算法哦

统计知识的应用 
按对象存活时间将对象分配到不同的内存区域,这些区域叫不同的分代 
垃圾回收针对分代对象的特征采用适宜的算法进行回收

将内存再次分区,根据对象存活时间长短将其分配到不同的区域(分代)上,一般分代回收法将内存分成三代:
新生代Eden Gen:该内存区中的对象存活时间短,很快不可达,对象一般也比较小
老生代Old Gen:该内存区中主要是老对象(经过几次回收后还可达的对象)、大对象,占用空间比新生代多
永生代:方法区

内存分配规则及gc算法:
1、新对象一般在新生代Eden中分配,Eden区没足够内存时触发新生代的一次Minor GC,Eden中对象很快死去,基本采用的是 复制算法copying:将内存均分,每次在其中一块分配对象,快用完时将还活着的对象都复制到 另一块上,清空已使用的那块即可。代价是内存减半,一点优化是不均分,而分为一块较大的Eden区和两块较小的survivor区,因为存活的对象不多。每次使用一块survivor和eden,gc时将其中的或对象都拷贝到未使用的那个survivor中,如果那个没使用的survivor空间不够则直接担保分配到 老生代,如果老生代都不够则进行老生代的gc(full Gc)。


2、大对象(很长的字符串、数组等)直接在老生代分配
分代转换:新生代中的对象经过几次gc后仍然存在,达到-XX:MaxTenuringThreshold配置的年龄值(次数)时,这些对象 晋升(转移)到老生代;
分配担保:minor gc会检测之前每次回收晋升到老生代的对象容量的平均值作为经验值,与老生代的剩余空间作比较,如果大于,则直接对老生代进行major gc(Full gc),如果小于,且存活的对象大于survivor空间,则该对象也转移到老生代
老生代存活的对象多且大,一般采用标记清理或标记-整理方法来gc

有了以上内存区的分代和几种基本gc算法,产生了多种具体的垃圾收集器

具体实现

7、JDK的垃圾收集器

JDK7一共有5种GC类型:

参考吧:http://www.importnew.com/1993.html

  1. Serial GC
  2. Parallel GC
  3. Parallel Old GC (Parallel Compacting GC)
  4. Concurrent Mark & Sweep GC  (or “CMS”)
  5. Garbage First (G1) GC

© 著作权归作者所有

共有 人打赏支持
qingfeng哥

qingfeng哥

粉丝 44
博文 124
码字总数 63706
作品 0
湛江
技术主管
加载中

评论(1)

jdk2010
jdk2010
mark
Java GC系列:Java垃圾回收详解

Java的内存分配与回收全部由JVM垃圾回收进程自动完成。与C语言不同,Java开发者不需要自己编写代码实现垃圾回收。这是Java深受大家欢迎的众多特性之一,能够帮助程序员更好地编写Java程序。 ...

满风
2015/04/10
0
0
My java——JVM(垃圾回收)四

续My java——JVM(内存域) 中讲述了Java在JVM中的内存使用,其实在我们出来java程序时基本上有两个地方的内存处理 一是栈、二是堆,JVM会自动回收堆中的内存,也就我们所说的垃圾回收,那J...

tngou
2013/03/20
0
0
Java finalize方法

《JAVA编程思想》: java提供finalize()方法,垃圾回收器准备释放内存的时候,会先调用finalize()。 (1).对象不一定会被回收。 (2).垃圾回收不是析构函数。 (3).垃圾回收只与内存有关。 (4)....

清风伴月
2017/10/22
0
0
《成神之路-基础篇》JVM——垃圾回收(已完结)

Java内存模型,Java内存管理,Java堆和栈,垃圾回收 本文是[《成神之路系列文章》][1]的第一篇,主要是关于JVM的一些介绍。 持续更新中 Java之美[从菜鸟到高手演变]之JVM内存管理及垃圾回收 ...

05/05
0
0
JVM性能优化, Part 3 垃圾回收

ImportNew注:本文是JVM性能优化 系列-第3篇-《JVM性能优化, Part 3 —— 垃圾回收》 第一篇 《JVM性能优化, Part 1 ―― JVM简介 》 第二篇《JVM性能优化, Part 2 ―― 编译器》 Java平台...

梁杰_Jack
2014/10/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSX | SafariBookmarksSyncAgent意外退出解决方法

1. 启动系统, 按住⌘-R不松手2. 在实用工具(Utilities)下打开终端,输入csrutil disable, 然后回车; 你就看到提示系统完整性保护(SIP: System Integrity Protection)已禁用3. 输入reboot回车...

云迹
今天
4
0
面向对象类之间的关系

面向对象类之间的关系:is-a、has-a、use-a is-a关系也叫继承或泛化,比如大雁和鸟类之间的关系就是继承。 has-a关系称为关联关系,例如企鹅在气候寒冷的地方生活,“企鹅”和“气候”就是关...

gackey
今天
4
0
读书(附电子书)|小狗钱钱之白色的拉布拉多

关注公众号,在公众号中回复“小狗钱钱”可免费获得电子书。 一、背景 之前写了一篇文章 《小狗钱钱》 理财小白应该读的一本书,那时候我才看那本书,现在看了一大半了,发现这本书确实不错,...

tiankonguse
今天
4
0
Permissions 0777 for ‘***’ are too open

异常显示: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ......

李玉长
今天
5
0
区块链10年了,还未落地,它失败了吗?

导读 几乎每个人,甚至是对通证持怀疑态度的人,都对区块链的技术有积极的看法,因为它有可能改变世界。然而,区块链技术问世已经10年了,我们仍然没有真正的用上区块链技术。 几乎每个人,甚...

问题终结者
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部