GC工作机制

关于内存分配

java虚拟机是先一次性分配一块较大的空间,每次new的时候都在该空间上进行分配和释放,主要分为两种:静态内存和动态内存,编译时能确定的内存就是静态内存,即内存是固定的,系统一次性分配,比如int类型变量。在程序执行过程中才能确定内存大小的就是动态内存,比如java对象的内存空间。java栈、程序计数器、本地方法栈都是线程私有的,和线程状态一致,当方法结束内存也跟着回收。java堆和方法区只有在程序运行中才知道要创建那些对象,这部分内存的分配和回收都是动态的。

垃圾回收器

常用方法

引用计数法

给对象添加一个引用计数器,每当有一个地方使用,引用数加1,反之减1,为0就回收。缺点:若两个对象互相引用,但是却没有其他对象引用,则这两个对象为垃圾对象,引用数不为0无法回收。

可达性分析算法

以根集对象为起始点向上搜索,如果有对象不可达的话,即为垃圾对象。根集包含java栈中引用的对象、方法区常量池中引用的对象。

回收算法

标记-清除

分两个阶段:标记和清除,标记所有需要回收的对象,然后统一回收。缺点:效率低,回收之后产生大量碎片

标记-复制

把内存空间分配分配为两个相等的区域,每次使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在使用的对象复制到另一个区域当中。优点:复制成本小,不会产生碎片。缺点:需要两倍内存空间

标记-整理

分两个阶段:第一阶段从根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把存活对象向一段移动,清理边界以外的内存。

实际使用

分代收集算法

虚拟机常用算法,基于不同的对象生命周期不一样,采用 不同的收集方式,提高回收效率。比如http请求中的session对象、线程、socket连接等生命周期较长;而有的生民周期就比较短,比如string对象,由于其不变类的特性,有的在使用一次后即可回收。如果不进行对象存活时间区分,每次垃圾回收都是对整个堆空间进行回收,消耗时间长,对生命周期较长的对象进行无用扫描,浪费资源,所以进行对象代的划分,把不同生命周期的对象放在不同代上。

年轻代(Young Generation)

所有新对象产生的地方,年轻代被分为三个部分:Enden区和两个Survivor区(From和To),当Enden区被对象填满时,就会执行GC,并把存活的对象转移到Survivor区,GC再次检查存活对象,再转移到另一个Survivor区,转移一次对象年龄就+1。这样一段时间内,总有一个空的Survivor区,通过年龄阈值来决定有资格升到老年代的对象,年龄阈值默认为15。
注意:如果Survivor区大于等于某个年龄的对象超过了Survivor区空间的一半,那么大于等于这个年龄的对象直接进入老年代,不需要再达到年龄阀值;大对象因为需要大量连续的空间,直接进入老年代。

老年代(Old Generation)

在年轻代中经历了N次回收仍然存活的对象就会被放到老年代。老年代的回收通常是内存占满之后触发Full GC回收整个堆空间——包括年轻代和年老代。

持久代(Permanent Generation)

用于存放静态文件,比如java类、方法等。类定义成员,但没有实际空间,与java对象回收关系不大,类实例化的对象占有实际空间,垃圾回收器回收的是无任何引用对象占据的空间,而不是对象本身。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值