美文网首页JavaJVM虚拟机&字节码底层术篇幅&JAVA进阶
Java - JVM TLAB、对象在内存中安置顺序、垃圾收集、

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

作者: ThingLin | 来源:发表于2017-08-13 23:36 被阅读145次

    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

    相关文章

      网友评论

        本文标题:Java - JVM TLAB、对象在内存中安置顺序、垃圾收集、

        本文链接:https://www.haomeiwen.com/subject/rxserxtx.html