第三章 : 垃圾收集器与内存分配策略

标记为垃圾:
    引用计数法 : 即当有一个地方引用A对象时,计数器就+1,当引用失效时,计数器-1.当为0时就可以回收了.
        这样有个问题就是当两个可以回收的对象相互引用,这样引用不为0,不能自动回收.
    目前主流的java虚拟机没有用引用计数法来管理内存.

    可达性分析法 : 当对象与GC Roots没有可以到达的路径时,表示为可回收对象
            GC Roots包括4种 : 
                    虚拟机栈(栈帧的本地变量表)中引用的对象
                    方法区中类静态属性引用的对象
                    方法区中常量引用的对象
                    本地方法栈中JNI(一般说Native方法)引用的对象
    当第一次标记之后,如果对象没有重写finalize或finalize()方法没有被虚拟机调用过,则会放置到F-Queue中.等待第二次被标记.
    可达性分析法需要 标记两次,第二次在finalize()方法放置的F-Queue中进行,当一个对象在第二次标记之前被"拯救"了,那么下次被可达性标记,则会立即回收,因为finalize()已经被执行过.

   引用的4中强度
         强引用 : 声明对象时的引用
        软引用 : 通过SoftRefrence类来实现,将要发生内存溢出时会回收
        弱引用 : 通过WeakRefrence类来实现 , 会被回收
        虚引用 : 通过PhantomRefrence类来实现 , 无法利用此引用获取对象 , 在此对象被回收时会接收到一个系统通知. 
回收 : 
    标记-清除算法
        可达性分析,然后直接回收 , 缺点 : 1.标记和清除效率都不高. 2 .容易产生内存碎片,当有大的对象需要存储时,又需要回收.
    复制算法
        将内存分为两块,把不需要回收的对象复制到另一侧,然后统一回收垃圾一侧.(IBM公司研究为新生代8:1,10%被浪费) , 缺点 : 内存被浪费
    标记-整理算法
       将所有存活的对象向一端移动,然后清理掉边界以外的内存
    分代收集算法
        将对象赋予年龄(新生代和老年代),然后根据年龄来选取不同的回收算法
HotSpot的算法实现
    枚举根节点(寻找引用)
        GC会有停顿,在编译后的代码中,有一个 OopMap的数据结构,存储了普通对象指针的引用地址.
    安全点
        因为HotSpot不会为每条指令都生成OopMap,所以需要在特定的位置记录这些信息,这些位置称之为安全点,点程序执行到达安全点时才能暂停.
        到达安全点有两种方式 : 
            抢先式中断 : GC时中断所有线程,然后让没在安全点的线程恢复运行,让其"跑"到安全点上( 现在几乎没有虚拟机采用此种)
            主动式中断 :  当需要GC时,设置一个标志,然后各个线程会主动的轮询这个标志,当为真时,会中断线程.
    安全区域
        当线程处于Sleep或Blocked状态时,无法响应JVM的中断请求,这时候又不会引起引用的变化,对于这种就需要安全区来解决,当执行到安全区的代码时,会标识自己
        已经进入到了Safe Region,那样当JVM发起中断请求时,就不管已经进入安全区的线程了,当离开安全区时,需要检查系统是否已经完成根节点枚举(或者整个GC过程)
    7种垃圾收集器
        Serial(串行)(新生代copy算法)
            以单线程的方式去收集,并在收集的时候将所有用户线程暂停掉,特点:简单高效

        ParNew(并行 新生代copy算法)
            是Serial的多线程版本,共用了相当多的代码.当然在单CPU上运行效率没有Serial快.在收集的时候,依然会暂停用户线程.属于并行收集器.(并发收集器则是用户和垃圾同时进行(也可能交替))

        Parallel Scavenge(并行 新生代copy算法)
            和前面的关注点不同,前面的是关注每次停顿用户线程的时间,而Parallel Scavenge则是关注的吞吐量 = 运行用户代码时间 / (运行用户代码 + 垃圾收集时间) , 另外还有一个自适应调节策略,会
            根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供合适的停顿时间或最大的吞吐量.参数是-XX:+UseAdaptiveSizePolicy

        Serial Old(串行 老年代标记-整理算法)
            是Serial收集器的老年代版本 . server模式下( server模式和client模式是什么意思?)两个用途 : 在1.5以前是搭配Parallel Scavenge使用,另一个用途是作为CMS收集器的后备预案

        Parallel Old
            解决Parallel Scavenge和Serial Old搭配不合,实现名副其实的"吞吐量优先"收集器.

        CMS(标记-清除算法)(并发收集低停顿收集器)
            包括4步:
                初始标记(停顿)(GC Roots标记过程)
                并发标记(GC Roots tracing过程)
                重新标记(停顿)(处理并发标记期间程序继续运作导致已标记部分变动的标记记录)
                并发清除
            3个明显缺点 : 
                *默认启动的回收线程数是(CPU数量 + 3) / 4 , 也就是当CPU在4个以上时,并发回收时垃圾线程不少于25%的CPU资源,所以当CPU数量少时,难以接受.
                *无法处理"浮动垃圾"(在GC期间,程序运行时产生的垃圾),当老年代使用达到一个阈值(1.5默认68%)的时候会触发CMS,如果剩下的空间不够装运行时使用,会导致"Concurrent Mode Failure"
                *"标记-清除"法会产生大量碎片,虚拟机可以设置是否开启碎片的整理以及整理的频率,默认是每次Full GC之后都会压缩(整理)
        G1(整体看是标记-整理,region看是copy算法)(其将堆分为一个个的region)
            与其他GC收集器相比具有4个特点
  • 并行与并发
  • 分代收集
  • 空间整合 (整体看是标记-整理,region看是copy算法)
  • 可预测的停顿(能够建立可预测的停顿模型)
            步骤
  • 初始标记(串行)
  • 并发标记(并发)
  • 最终标记(并行)
  • 筛选回收(并行)
GC日志
    [ Full GC 283.736 : [ParNew : 261599-> 261599( 261952) , 0.0000288 secs ]]
  • GC的停顿类型,有Full则表示发生了Stop-The-World停顿
  • GC发生的时间,从启动JVM开始计算
  • 发生GC的区域
  • GC前已使用的容量
  • GC后使用的容量
  • 总容量
  • GC消耗的时间,单位是秒
内存分配与回收策略
    新生代中Eden区和Survivor区比例是8:1,并且对象优先进入Eden区.
    大对象直接进入老年代 : 因为年轻代使用的是copy算法,所以建议大对象直接进入老年代,-XX:PretenureSizeThreshold参数,令大于这个值的对象直接进入老年代分配.(Parallel Scavenge不认识这个参数)

    长期存活的对象进入老年代 : 虚拟机给每个对象定义了年龄计数器,对象在Eden出生并经过一次Minor(年轻代)GC后任然存活.并且能被Survivor区容纳的话,年龄则为1,每经历一次Minor GC年龄加1,默认15岁
    会晋升到老年代中.晋升的阈值可以通过-XX:MaxTenuringThreshold参数设置.

    动态对象年龄判断 : 如果在Survivor空间中相同年龄所有对象大小的总合大于Survivor空间的一半,则年龄大于或等于该年龄的对象就可以直接进入老年代,不需要等到年龄的阈值.

    空间分配担保 : 在发生Minor GC时,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有的对象,如果不大于,会查看HandlePromotionFailure设置值是否允许担保失败.如果允许,则查看
    空间是否大于历次晋升到老年代对象的平均大小,如果小于,则进行Full GC.当担保失败后,也会进行Full GC.(在JDK6 update 24之后,不会判断HandlePromotionFailure设置,默认为true)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值