java虚拟机之路-垃圾收集器与内存分配策略

    java与c++之间有一堵由动态分配和垃圾收集技术所围成的高墙,墙内的想出去,墙外的人却想进来。

1.概述

    垃圾收集是要比java更加久远的技术。程序计数器、虚拟机栈、本地方法栈这些都是线程私有的,随线程而生或灭,所以这部分的垃圾很好收集。堆或者方法区中,对象是在运行时动态创建的,所以只有在运行时才能知道创建那些对象,分配多少内存,方法的分支需要的内存是不一样的。垃圾收集主要是对堆中和方法区中的内存进行回收。

2.如何判定对象存活?

     1.引用计数。给对象添加一个引用计数器,当引用计数器为0时,对象死亡。这个方法最大的问题就是循环引用问题。若A是B的引用,B也是A的引用,除此之外,再无引用,实际上这2个对象都不能在被访问了,由于他们之间的计数不为0,所以无法回收。

    2.可达性算法

     选一个gcroot,用引用关系构成一颗树,如果树被截断,则截断的节点都要被回收。java中采用这种方法来判断对象是否回收。首先进行GC时,需要stop the world即终端所有线程,因为不能一边进行GC,一边对象之间的引用关系发生变化。虚拟机中设有OopMap这个数据结构来记录那些位置是引用,如果为每条指令都生成OopMap需要的开销太大,所以虚拟机中设有安全点和安全区域。在走到安全点的时候,才进行GC。java虚拟机采用抢先式的方式终端线程。即线程如果未到达安全点,则回复线程到达安全点再中断。安全区域是为程序到达安全点所需的时间较长,即程序内存在循环,虚拟机不可能等待线程执行完,所以设置有安全区,在安全区内引用关系不会变化。

    4.生存还是死亡 

    我们都知道可以在类中定义finalize()方法,这个方法是在对象死亡前调用的,所以这个方法也不一定会调用,如果一直没进行垃圾收集,finalize()方法也不会调用。当进行垃圾收集时,会调用finalize()方法,如果对象在方法中成功被别的对象引用,这个对象就不会被回收。记住finalize()只调用一次,下次再回收该对象时,如果finalize()执行过一次,就不会再调用,直接回收该对象。这个方法一般还是不要用,这就是java为了安慰c++程序员设计的,和析构函数差别很大。

    5.方法区回收

   方法区中存的是静态变量、加载过的类信息,这些都是存在老年代中的东西,回收效率比较低。

3.垃圾收集算法

    这里终于讲到了重点,哈哈哈~~~~~

   1.标记-清除算法

     把需要回收的内存块标记然后清理。这么做有很大的缺点,会产生很多的内存碎片,这样就没法对大的对象进行内存分配,再就是效率不高。

    2.复制算法

     就是内存分为2部分,一半存储对象(A),另一半用来清理(B)。通过将A中存活的对象复制到B中,再将A清空,实现垃圾收集。

   3.标记整理算法

     对要回收的对象进行标记,然后没被回收的对象前移,讲最后边的内存清空。这样的优点就是没有内存碎片,

    4.分代收集算法

    把JAVA堆分成新生代和老年代。新生代采用复制算法,老年代采用“标记-清理算法”或者“标记-整理算法”。新生代划分为eden区和2个Suivivor区,每次将新生代中的eden和Survivor中的对象复制到另一个Survivor中,eden区占80%,Survivor占10%,所以只有10%的空间被浪费了。

4.CMS收集器

    目前很大一部分java应用在互联网或者B/S系统中,这类系统需要的延时低。CMS收集器就很符合。

    1.初始标记

    2.并发标记

    3.重新标记

    4.并发清除

    初始标记和重新标记需要stop the world。初始表示是标记GCroot直接相连的节点,并发标记随用户进程一起遍历。重新标记是为了标记在并发标记期间导致引用关系变化的那一部分。并发清除就是收集垃圾。

    优点:低停顿,并发

    缺点:1.占用cpu资源。如果CPU资源本来就少,再运行垃圾收集会让系统负载更大。

               2.标记清楚算法的缺点

               3.在标记之后产生的垃圾无法回收,只能等待下一个周期。这种垃圾被称为“浮动垃圾”。

5.内存分配和回收策略

      1.对象优先在eden区分配

      2.大对象直接进入老年代

      3.长期存活的对象进入老年代

  空间分配的担保:备份是由其中一个suivivor进行的,如果这个suivivor放不下存活的对象,这就需要老年代来担保内存的分配,如果老年代也放不下,只好进行full gc。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值