Java - JVM TLAB、对象在内存中安置顺序、垃圾收集、回收算法

23 篇文章 0 订阅
3 篇文章 0 订阅
1.TLAB

TLAB Thread Local Allocation Buffer,JDK1.7默认开启TLAB一般不需要去设置,TLAB极大提高程序性能,它是Java的一个优化方案。

    -XX:+UseTLAB    开启TLAB
    -XX:+PrintTLAB  打印TLAB信息
    -XX:+TLABSize   设置TLAB大小
    -XX:TLABRefillWasteFraction 设置维护进入TLAB空间单个对象大小,比例值,默认1/64,对象大于该值会去堆创建。
    -XX:ResizeTLAB  自调整TLABRefillWasteFraction 阀值。
image.png

测试

    public static void alloc(){
        byte[] b = new byte[100];
        byte[] b2 = new byte[100];
    }
    
    public static void main(String[] args) {
        long begin = System.currentTimeMillis();
        for(int i=0; i<200000000;i++){
            alloc();
        }
        System.out.println("耗时"+(System.currentTimeMillis() - begin));
    }

配置TLAB的运行结果

-XX:+UseTLAB -XX:+PrintTLAB
image.png

配置禁用

-XX:-UseTLAB -XX:+PrintTLAB
image.png

配置TLAB性能高很多,这和对象的安置优先选择的顺序有关系。

2.安置顺序

创建一个对象会尝试在栈上分配,不能分配栈上其次尝试TLAB,再其次是老年代,最后选择是年轻代的Eden,老年代和Eden都是堆内存中。

image.png
3.垃圾收集算法

1:引用计数
  对象被引用时计数器+1,引用失效时-1,这个算法有一些问题,循环引用情况不好处理,频繁+-操作比较耗费性能。

2:标记清除
  分为标记和清除两个阶段处理内存中的对象,这种方式弊端是会产生空间碎片,垃圾回收后的空间不连续。

3:复制
  将内存空间分为两块(如from和to),每次使用一块,垃圾回收时,将正在使用的对象复制到另外一个区将可回收的对象留在当前区,再把当前区的对象都回收。

4:标记压缩
  在标记清除的基础上做了优化,把存活对象压缩到一端然后进行垃圾清理,老年代中使用的上标记压缩的方法。

5:分代算法
  根据对象特点把内存分成多块,而后根据每块内存的特点使用不同的算法。新生代回收频率很高,但是每次回收耗时很短,而老年代回收频率较低耗时比较长,所以会尽量减少老年代的GC。

6:分区算法
  将整个内存分成多个独立的空间,每个空间可以独立使用,能够细粒度控制回收那些小空间不用一次把整个内存空间GC。

4.垃圾收集器

垃圾收集器决定了堆内存的格局,有的回收器没有把堆新生代分成eden、from、to是在策略不同,而使用from、to(拷贝、肃清)是为了保证内存空间的连续性。

1:串行垃圾收集器 -XX:+UseSerialGC
  使用单线程进行垃圾回收器。每次回收时一个线程工作,对于并行能力较弱的计算机来说,串行回收器的专注性和独占性会有更好的性能表现。串行回收器可以在新生代和老年代使用,根据作用于不同堆空间分为新生代串行回收器和老年代串行回收器。

image.png

2:并行垃圾收集器-XX:+UseParNewGC
  并行回收器在串行回收器基础上做了改进,它使用多个线程同时进行垃圾回收,对于计算能力强的计算机而言,可以有效的缩短垃圾回收所需的实际时间。
  ParNew回收器是一个工作在新生代的垃圾收集器,其是多线程的,但是回收策略和算法同串行回收器一样。配置-XX:ParallelGCThreads指定线程数量。

image.png

3:并行回收器-XX:+UseParallelGC
  新生代ParallelGC回收器,使用复制算法的收集器,也是多线程独占形式的收集器。ParallelGC回收器非常关注系统的吞吐量。
  -XX:MaxGCPauseMillis设置最大垃圾收集停顿时间,参数设置小了会引起频繁GC会降低吞吐量。
  -XX:GCTimeRatio设置吞吐量大小,是一个百分比(0-100整数),默认情况下99,系统会花不超过1/(1+n)的时间用于垃圾回收,也就是1/(1+99)=1%的时间。
  -XX:+UseAdaptiveSizePolicy设置打开自适应模式,在这种模式下,新生代空间、eden、from/to的比例,以及晋升老年代的对象年龄参数都自动调整,能达到在堆大小、吞吐量和停顿时间之间的平衡点。

image.png

4:并行回收器-XX:+UseParallelOldGC
  老年代回收器ParallelOldGC是多线程的回收器,是一个关注吞吐量的回收器,使用标记压缩算法。
  -XX:+ParallelGCThreads配置线程数量。

image.png

5:CMS回收器-XX:+UseConcMarkSweepGC
  Concurrent Mark Sweep并发标记清除。
  CMS不是独占的回收器,CMS回收过程中程序的其它线程不会停止工作,所以必须保证内存足够使用,如果在CMS工作的时候内存不够使用会回收失败,回收失败时虚拟机会启动老年代串行回收器进行垃圾回收,此时程序会中断。
  -XX:CMSInitiatingOccupancyFraction指定使用内存到一定阀值CMS就会去回收,默认是68(60%)。
  -XX:+UseCMSCompactAtFullCollection设置CMS回收完成后进行一次碎片整理。
  -XX:CMSFullGCsBeforeCompaction设置进行多少次CMS回收之后进行一次内存压缩。

image.png

6:G1回收器-XX:+UseG1GC
  Garbage-First,在Jdk1.7开始出现的垃圾回收器。G1回收器的独特的垃圾回收策略,G1属于分代垃圾回收器,区分新生代和老年代,不要求整个eden区或者新生代、老年代的空间都连续,它使用了分区算法。
  G1可多线程工作,G1在工作的时候程序可以正常运行。
  G1回收器是分代收集器,但它是兼顾新生代和老年代一起工作。
  G1在回收过程中会使用复制对象方式减少空间碎片。
  G1由于分区的原因,可以分区进行回收,缩小了回收的范围,提升性能。
  -XX:MaxGCPauseMillis 最大停顿时间。
  -XX:ParallelGCThreads 线程数量。

image.png


作者:ThingLin
链接:https://www.jianshu.com/p/c2b24c5698dd
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值