文档章节

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哥

粉丝 45
博文 127
码字总数 64346
作品 0
湛江
技术主管
私信 提问
加载中

评论(1)

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

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

满风
2015/04/10
0
0
Java finalize方法

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

清风伴月
2017/10/22
0
0
JVM系列第9讲:JVM垃圾回收器

前面文章中,我们介绍了 Java 虚拟机的内存结构,Java 虚拟机的垃圾回收机制,那么这篇文章我们说说具体执行垃圾回收的垃圾回收器。 总的来说,Java 虚拟机的垃圾回收器可以分为四大类别:串...

陈树义
2018/11/22
0
0
My java——JVM(垃圾回收)四

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

tngou
2013/03/20
0
0
《成神之路-基础篇》JVM——垃圾回收(已完结)

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

2018/05/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Linux Wireshark普通用户启动使用方案

当系统安装好Wireshark后请正常启动是否可以进行正常使用,如果不行请参考下列指导 向系统添加一个用户组 sudo groupadd wireshark //如提示此组存在可跳过 将指定用户添加到这个组中 sudo...

CHONGCHEN
今天
1
0
CSS 选择器参考手册

CSS 选择器参考手册 选择器 描述 [attribute] 用于选取带有指定属性的元素。 [attribute=value] 用于选取带有指定属性和值的元素。 [attribute~=value] 用于选取属性值中包含指定词汇的元素。...

Jack088
今天
2
0
数据库篇一

数据库篇 第1章 数据库介绍 1.1 数据库概述  什么是数据库(DB:DataBase) 数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据...

stars永恒
今天
4
0
Intellij IDEA中设置了jsp页面,但是在访问页面时却提示404

在Intellij IDEA中设置了spring boot的jsp页面,但是在访问时,却出现404,Not Found,经过查找资料后解决,步骤如下: 在Run/Debug Configurations面板中设置该程序的Working Directory选项...

uknow8692
昨天
4
0
day24:文档第五行增内容|每月1号压缩/etc/目录|过滤文本重复次数多的10个单词|人员分组|

1、在文本文档1.txt里第五行下面增加如下内容;两个方法; # This is a test file.# Test insert line into this file. 分析:给文档后增加内容,可以用sed 来搞定;也可以用while do done...

芬野de博客
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部