Java GC的基本原理

                                                         Java 垃圾回收机制[内存管理]

1.对象和垃圾:
   a) 新建对象Dog d = new Dog(); 一个变量指向一个对象,系统会在堆内存中分配一块空间
  b) 当对象不再被任何变量引用的时候,这块内存就成为了垃圾,等待GC 回收
2.GC的特征:
  a) GC 只负责回收堆内存中的对象,而不会回收物理资源.(如网络io,数据库连接等)
  b) GC 无法被精确控制,会在适当的是时候进行,当变量不再不被引用时回收
  c) GC在回收任何对象之前,总会调用它的finalize 方法,该方法可能是该对象重新激活,
从而导致回收失败.
3.内存分配方式

     每个Java 线程都拥有自己的内存栈(stack).用来存放局部变量和返回值,栈是在线程启动时分配的.
     所有的线程共享一个内存堆(heap),所有运行时的内存分配都在堆上进行.换句话说就是所有的对象都是在堆上创建的.堆是在Java 虚拟机启动时分配好的.

                           Java 虚拟机的内存模型
-从静态存储去分配,内存在程序编译时就分配好了,例如static 变量
-在栈上创建,各种原始数据类型的局部变量,都是在栈上创建的.当程序退出该变量的作用范
围时,这些变量的内存会被自动释放.
-在堆中创建.对象都是在堆中创建的.程序运行的时候用new 创建对象,对象创建时会在堆中
为其分配内存.

堆的空间由自动的存储管理系统进行控制.也就是Garbage Collector.垃圾收集器通常作为一
个独立的线程运行.

 

  4.分代复制垃圾收集器
HotSpot Java 虚拟机使用分代复制(generational copying)算法.分代复制算法基于这样一个事
实——超过95%的对象的生存期都非常短.分代复制算法根据对象的生存期将对分为两代.
所有新创建的对象都在一个类似栈的内存区域进行分配,这块区域叫做eden.这首先使得内存
分配的速度提高了.因为此时只需要更新eden 的指针和检查eden 溢出就可以了.
当eden 区域已经全部分配给对象时,大部分对象已经”死亡”了.垃圾收集器只有将少量未死亡的长期对象(tenured 对象)复制到另一块内存中去,然后直接更新eden 的指针就可以了.

 
生存于eden 中的对象称为年轻代(young generation),生命较长的对象区域称为年老代(old
generation). 分代就是指分为年老和年轻两代.这是根据生命周期的长短来划分的.
    复制是指当eden 的内存区域分配完毕,GC 就会对eden 进行一次次要垃圾收集(minor
collection),将仍然被引用的对象复制到old generation.,并更新指向这些对象的引用,然后将
eden 全部清空.
      分代复制的效率非常高,因为清空eden 花费的时间极少,主要的时间花费在复制上.因此,适当调整eden 的大小,增长或缩短较小的垃圾收集发生的周期,当较小的垃圾收集发生时,更
多的对象已经死亡,从而减少需要复制的对象的数量,加快程序的速度.
      当old generation 的内存区域全部分配完时,垃圾收集器会进行一次主要垃圾收集(majorcollection).主要垃圾收集通常比次要垃圾收集慢,因为所有”存活”的对象都会被遍历到.
可见次要垃圾回收是指将”存活”对象复制到old generation 内存区域中,那么主要垃圾收集
又是如何进行的呢?


5.标记垃圾收集器
     在年老代中,通常采标记用垃圾收集器,这种垃圾收集器从一组根引用开始,遍历所有的对
象,如果一个对象被根引用,那么就标记为”存活”,而存活对象引用的对象也被标记为”存活”,如此循环,其余对象则被标记为”死亡”.死亡的对象会被回收.
根据对存活对象处理方法的不同,标记垃圾收集器又分为两类:
    1) 标记紧缩垃圾收集器(mark-and-compact collector) 将所有存活的对象复制到一个连
续的内存区域中,因此可以有效地减少内存碎片
    2) 标记清除垃圾收集器(mark-and-sweep collector) 保留所有的存活对象,而将所有的死亡对象的内存空降记录到一个自由空间列表中,虽然连续的死亡对象空间会被合并,
但与标记紧缩垃圾收集器相比,这种方法仍然会产生较多的内存碎片.
同复制方式相比,紧缩方式和清除方式要慢得多,因此标记垃圾收集器只用来收集年老代.
6.增量垃圾收集器
     运行标记紧缩垃圾收集器或者标记清除垃圾收集器,对运行的程序来说,都是一场灾难.因
为这些垃圾收集器在运行的时候,会停止JVM 中其他程序的线程.而且这些垃圾收集器每次
都会收集多有的垃圾内存,因此每次停顿的时间是不可预测的.分代复制垃圾收集器的情况稍
好一点,但也会造成明显的停顿.
增量垃圾收集器能够提供接近于常数的固定的暂停时间,这个暂停短到用户可以忽略它,因
此增量垃圾收集器特别适用于操纵大量数据的应用程序,以及对交互性要求比较高的程序.
它的基本原理是时间较长的年老代的垃圾收集分为许多的间隔来完成.每次只收集一部分
内存.对于用户来说好像完全没有停顿一样.但是增量垃圾收集器并不能精确地保证停顿的时
间,根据JVM 的实现可以应用与不同要求.

7.次要收集和主要收集
HotSpot JVM 的内存对包括4 种空间.一个permanent generation;一个old generation;一个eden 和两个survivor space.enden 和两个survivor space 合称young generation.
 
1)堆空间包含这四种区域
堆的大小由参数-Xms 和-Xms 控制.
-Xms 指定堆大小的下限就是创建时的堆的大小
-Xmx 指定堆大小的上限就是Java 虚拟机运行时可以扩展堆的大小
如果-Xms 和-Xmx 相等则堆大小是不变的
eg.
-Xms268435456 –Xmx26843456
就表示启动JVM 时堆的大小是256MB,并且运行时堆的大小始终为256MB.
扩展参数-XX:MinHeapFreeRatio,指定的是一个百分比,如果垃圾回收之后堆的剩余空间
低于这个百分比,那么就扩展堆.
扩展参数-XX:MaxHeapFreeRatio,指定的是一个百分比,如果垃圾回收之后堆的剩余空间
高于这个百分比,那么就减小堆.
eg.
-XX:MinHeapFreeRatio=40
表示剩余空间低于40%时扩展堆的大小
-XX:MaxHeapFreeRatio=70
表示剩余空间大于70%时减小堆的大小
2)permanent generation
保留给JVM 存放类和方法的反射(reflection)对象
扩展参数-XX:MaxPermSize, 指定permanent generation 大小的上限
eg.
-XX:MaxPermSize=64m
表示指定permanent generation 为”64m”;
3)old generation
用来存放tenured 的对象.参数-XX:NewRatio 用来指定old generation 和young generation 之
比.
eg.
-XX:NewRatio=4 表示old generation 和young generation 之比为4.
4)young generation
young generation 包含一个eden 和两个survivor space.参数-XX:NewRatio 指定old generation
的同时也指定了young generation 的大小.此外,参数-Xmn 可以直接指定young generation 的
大小.与-Xmn 对应的是-XX:NewSize 和-XX:MaxNewSize. 分别指定young generation 的初始
大小和上限
eg.
-Xmn64MB 表示young generation 的大小是64MB
5)eden
eden 用来存放新建的对象.survivor space 用来存放尚未tenured 的对象.eden 和survivor space
的大小由-XX:SurvivorRatio 决定.
eg.
-XX:SurvivorRatio=64,表示eden 和survivor space 之比为64(young generation 分为66 份).由于survivor
有两个,因此survivor space 的大小是young generation 的1/66,eden 则是young generation 的32/33.
6)survivor space
当eden 空间被分配完时,就会发生一次次要垃圾收集(minor collection).eden 中仍然存活的
对象会被复制到survivor space1 中,其他对象直接丢弃,其占用的内存被回收.在一次次要垃圾
回收之后,JVM 继续在eden 中创建对象.当eden 的空间再次被分配完的时候,又会发生一次次
要垃圾收集.将eden 中存活的对象复制到另一个survivor space2 中,并且为survivor 中的每一
个对象计算年龄age 和存活期threshold。age 是对象在复制到old generation 之前经历过的次
要垃圾收集的次数.threshold 则是表示在这一次的次要垃圾收集将会被复制到old generation
的对象的age。age 小于threshold 的将会被复制到survivor space2 中这些对象被称为aged 对
象(老化对象)。而清空的survivor space1 为下一次的次要垃圾收集中复制的目的地.

7)主要垃圾收集
在old generation 中的内存也告罄的时,就会发生一次主要垃圾收集.主要垃圾收集采用标记
紧缩的方法,在old generation 中标记出所有存活的对象,然后将其它对象回收.主要垃圾收集
通常要比次要垃圾收集的时间长的多,因为标记和回收都是很费时的操作.在典型的配置
中,old generation 也比young generation 要大(以达到多进行次要收集少进行主要收集的目的).
堆的内存区域和相应的主要配置参数
[完整的扩展参数配置参考 http://java.sun.com/docs/hotspot/VMOption.html]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值