转载

【深入浅出-JVM】(37):对象从新生代到老年代过程

-Xmx64M -Xms64M -XX:+PrintGCDetails
package com.mousycoder.mycode.thinking_in_jvm;

/**
 * @version 1.0
 * @author: mousycoder
 * @date: 2019-07-15 18:06
 */
public class AllocEden {

    public static final int _1K = 1024;
    public static void main(String[] args) {
        for (int i = 0; i < 5 * _1K; i++) {
            byte[] b = new byte[_1K];
        }
    }
}

输出

Heap
 PSYoungGen total 18944K, used 7250K [0x00000007beb00000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 16384K, 44% used [0x00000007beb00000,0x00000007bf214968,0x00000007bfb00000)
  from space 2560K, 0% used [0x00000007bfd80000,0x00000007bfd80000,0x00000007c0000000)
  to space 2560K, 0% used [0x00000007bfb00000,0x00000007bfb00000,0x00000007bfd80000)
 ParOldGen total 44032K, used 0K [0x00000007bc000000, 0x00000007beb00000, 0x00000007beb00000)
  object space 44032K, 0% used [0x00000007bc000000,0x00000007bc000000,0x00000007beb00000)
 Metaspace used 2741K, capacity 4486K, committed 4864K, reserved 1056768K
  class space used 297K, capacity 386K, committed 512K, reserved 1048576K

没有 GC 发生,分配的 5M 对象都在 Eden 区

新生代对象晋升到老年代

-Xmx1024M -Xms1024M -XX:+PrintGCDetails -XX:MaxTenuringThreshold=10 -XX:+PrintHeapAtGC
package com.mousycoder.mycode.thinking_in_jvm;

import java.util.HashMap;
import java.util.Map;

/**
 * @version 1.0
 * @author: mousycoder
 * @date: 2019-07-16 10:05
 */
public class MaxTenuringThreshold {

    public static final int _1M = 1024 * 1024;
    public static final int _1K = 1024;

    public static void main(String[] args) {
        Map<Integer,byte[]> map = new HashMap<>();

        for (int i = 0; i < 5 * _1K; i++) {
            byte[] b = new byte[_1K];
            map.put(i,b);
        }


        for (int i = 0; i < 17; i++) {
            for (int j = 0; j < 270; j++) {
                byte[] g = new byte[_1M];
            }
        }

    }
}

输出

{Heap before GC invocations=1 (full 0):
 PSYoungGen total 305664K, used 261739K [0x00000007aab00000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 262144K, 99% used [0x00000007aab00000,0x00000007baa9acc0,0x00000007bab00000)
  from space 43520K, 0% used [0x00000007bd580000,0x00000007bd580000,0x00000007c0000000)
  to space 43520K, 0% used [0x00000007bab00000,0x00000007bab00000,0x00000007bd580000)
 ParOldGen total 699392K, used 0K [0x0000000780000000, 0x00000007aab00000, 0x00000007aab00000)
  object space 699392K, 0% used [0x0000000780000000,0x0000000780000000,0x00000007aab00000)
 Metaspace used 2737K, capacity 4486K, committed 4864K, reserved 1056768K
  class space used 296K, capacity 386K, committed 512K, reserved 1048576K
[GC (Allocation Failure) [PSYoungGen: 261739K->6128K(305664K)] 261739K->6136K(1005056K), 0.0044940 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
Heap after GC invocations=1 (full 0):
 PSYoungGen total 305664K, used 6128K [0x00000007aab00000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 262144K, 0% used [0x00000007aab00000,0x00000007aab00000,0x00000007bab00000)
  from space 43520K, 14% used [0x00000007bab00000,0x00000007bb0fc020,0x00000007bd580000)
  to space 43520K, 0% used [0x00000007bd580000,0x00000007bd580000,0x00000007c0000000)
 ParOldGen total 699392K, used 8K [0x0000000780000000, 0x00000007aab00000, 0x00000007aab00000)
  object space 699392K, 0% used [0x0000000780000000,0x0000000780002000,0x00000007aab00000)
 Metaspace used 2737K, capacity 4486K, committed 4864K, reserved 1056768K
  class space used 296K, capacity 386K, committed 512K, reserved 1048576K
}
`
`
`
{Heap before GC invocations=11 (full 0):
 PSYoungGen total 339456K, used 330101K [0x00000007aab00000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 330752K, 99% used [0x00000007aab00000,0x00000007bed15410,0x00000007bee00000)
  from space 8704K, 3% used [0x00000007bf780000,0x00000007bf7c8000,0x00000007c0000000)
  to space 9216K, 0% used [0x00000007bee00000,0x00000007bee00000,0x00000007bf700000)
 ParOldGen total 699392K, used 6401K [0x0000000780000000, 0x00000007aab00000, 0x00000007aab00000)
  object space 699392K, 0% used [0x0000000780000000,0x0000000780640468,0x00000007aab00000)
 Metaspace used 3065K, capacity 4486K, committed 4864K, reserved 1056768K
  class space used 341K, capacity 386K, committed 512K, reserved 1048576K
[GC (Allocation Failure) [PSYoungGen: 330101K->0K(339968K)] 336502K->6613K(1039360K), 0.0005330 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap after GC invocations=11 (full 0):
 PSYoungGen total 339968K, used 0K [0x00000007aab00000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 330752K, 0% used [0x00000007aab00000,0x00000007aab00000,0x00000007bee00000)
  from space 9216K, 0% used [0x00000007bee00000,0x00000007bee00000,0x00000007bf700000)
  to space 9216K, 0% used [0x00000007bf700000,0x00000007bf700000,0x00000007c0000000)
 ParOldGen total 699392K, used 6613K [0x0000000780000000, 0x00000007aab00000, 0x00000007aab00000)
  object space 699392K, 0% used [0x0000000780000000,0x0000000780675478,0x00000007aab00000)
 Metaspace used 3065K, capacity 4486K, committed 4864K, reserved 1056768K
  class space used 341K, capacity 386K, committed 512K, reserved 1048576K
}

`
`
`
{Heap before GC invocations=15 (full 0):
 PSYoungGen total 339968K, used 329747K [0x00000007aab00000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 330752K, 99% used [0x00000007aab00000,0x00000007bed04fb8,0x00000007bee00000)
  from space 9216K, 0% used [0x00000007bf700000,0x00000007bf700000,0x00000007c0000000)
  to space 9216K, 0% used [0x00000007bee00000,0x00000007bee00000,0x00000007bf700000)
 ParOldGen total 699392K, used 6613K [0x0000000780000000, 0x00000007aab00000, 0x00000007aab00000)
  object space 699392K, 0% used [0x0000000780000000,0x0000000780675478,0x00000007aab00000)
 Metaspace used 3065K, capacity 4486K, committed 4864K, reserved 1056768K
  class space used 341K, capacity 386K, committed 512K, reserved 1048576K
[GC (Allocation Failure) [PSYoungGen: 329747K->0K(339968K)] 336361K->6613K(1039360K), 0.0003440 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
Heap after GC invocations=15 (full 0):
 PSYoungGen total 339968K, used 0K [0x00000007aab00000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 330752K, 0% used [0x00000007aab00000,0x00000007aab00000,0x00000007bee00000)
  from space 9216K, 0% used [0x00000007bee00000,0x00000007bee00000,0x00000007bf700000)
  to space 8704K, 0% used [0x00000007bf780000,0x00000007bf780000,0x00000007c0000000)
 ParOldGen total 699392K, used 6613K [0x0000000780000000, 0x00000007aab00000, 0x00000007aab00000)
  object space 699392K, 0% used [0x0000000780000000,0x0000000780675478,0x00000007aab00000)
 Metaspace used 3065K, capacity 4486K, committed 4864K, reserved 1056768K
  class space used 341K, capacity 386K, committed 512K, reserved 1048576K
}

其实第 11 次的时候,新生代的 5M 对象已经晋级到老年代了,MaxTenuringThreshold 为充分非必要条件(达到次数一定晋升,没达到可能也晋升)

如果

-Xmx1024M -Xms1024M -XX:+PrintGCDetails -XX:MaxTenuringThreshold=10 -XX:+PrintHeapAtGC -XX:TargetSurvivorRatio=13

输出

{Heap before GC invocations=7 (full 0):
 PSYoungGen total 343040K, used 342362K [0x00000007aab00000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 336896K, 99% used [0x00000007aab00000,0x00000007bf36e968,0x00000007bf400000)
  from space 6144K, 98% used [0x00000007bfa00000,0x00000007bffe8010,0x00000007c0000000)
  to space 6144K, 0% used [0x00000007bf400000,0x00000007bf400000,0x00000007bfa00000)
 ParOldGen total 699392K, used 8K [0x0000000780000000, 0x00000007aab00000, 0x00000007aab00000)
  object space 699392K, 0% used [0x0000000780000000,0x0000000780002000,0x00000007aab00000)
 Metaspace used 2740K, capacity 4486K, committed 4864K, reserved 1056768K
  class space used 296K, capacity 386K, committed 512K, reserved 1048576K
[GC (Allocation Failure) [PSYoungGen: 342362K->0K(337408K)] 342370K->6397K(1036800K), 0.0042910 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
Heap after GC invocations=7 (full 0):
 PSYoungGen total 337408K, used 0K [0x00000007aab00000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 336896K, 0% used [0x00000007aab00000,0x00000007aab00000,0x00000007bf400000)
  from space 512K, 0% used [0x00000007bf400000,0x00000007bf400000,0x00000007bf480000)
  to space 7680K, 0% used [0x00000007bf880000,0x00000007bf880000,0x00000007c0000000)
 ParOldGen total 699392K, used 6397K [0x0000000780000000, 0x00000007aab00000, 0x00000007aab00000)
  object space 699392K, 0% used [0x0000000780000000,0x000000078063f458,0x00000007aab00000)
 Metaspace used 2740K, capacity 4486K, committed 4864K, reserved 1056768K
  class space used 296K, capacity 386K, committed 512K, reserved 1048576K
}

则第 7 次 GC 的时候,已经晋升到老年代了 (TargetSurvivorRatio=13 代表 S 区使用率超过 13%后,马上使用较小的 age 晋升到老年代)

直接分配到老年代

-Xmx32m -Xms32m -XX:+UseSerialGC -XX:+PrintGCDetails -XX:PretenureSizeThreshold=1000 -XX:-UseTLAB

-XX:-UseTLAB 禁用 TLAB -XX:PretenureSizeThreshold=1000 超过 1000 字节的对象直接分配到老年代

package com.mousycoder.mycode.thinking_in_jvm;

import java.util.HashMap;
import java.util.Map;

/**
 * @version 1.0
 * @author: mousycoder
 * @date: 2019-07-16 11:04
 */
public class PretenureSizeThreshold {

    public static final int _1K = 1024;

    public static void main(String[] args) {
        Map<Integer,byte[]> map = new HashMap<>();
        for (int i = 0; i < 5 * _1K; i++) {
            byte[] b = new byte[_1K];
            map.put(i,b);
        }
    }
}

输出

Heap
 def new generation total 9792K, used 924K [0x00000007be000000, 0x00000007beaa0000, 0x00000007beaa0000)
  eden space 8704K, 10% used [0x00000007be000000, 0x00000007be0e72e8, 0x00000007be880000)
  from space 1088K, 0% used [0x00000007be880000, 0x00000007be880000, 0x00000007be990000)
  to space 1088K, 0% used [0x00000007be990000, 0x00000007be990000, 0x00000007beaa0000)
 tenured generation total 21888K, used 5430K [0x00000007beaa0000, 0x00000007c0000000, 0x00000007c0000000)
   the space 21888K, 24% used [0x00000007beaa0000, 0x00000007befed868, 0x00000007befeda00, 0x00000007c0000000)
 Metaspace used 2743K, capacity 4486K, committed 4864K, reserved 1056768K
  class space used 297K, capacity 386K, committed 512K, reserved 1048576K

可见直接分配到老年代了

TLAB 分配对象

TLAB 是Thread Local Allocation Buffer 线程本地分配缓存,为了加速对象分配,避免堆共享同步

package com.mousycoder.mycode.thinking_in_jvm;

/**
 * @version 1.0
 * @author: mousycoder
 * @date: 2019-07-16 11:23
 */
public class UseTLAB {

    public static void alloc(){
        byte[] b = new byte[2];
        b[0] = 1;
    }

    public static void main(String[] args) {
        long b = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            alloc();
        }
        long e = System.currentTimeMillis();
        System.out.println(e -b );
    }
}

开启 TLAB ,启用函数 JIT,禁止逃逸分析和后台编译

-XX:+UseTLAB -Xcomp -XX:-BackgroundCompilation -XX:-DoEscapeAnalysis -server

输出

关闭 TLAB

-XX:-UseTLAB -Xcomp -XX:-BackgroundCompilation -XX:-DoEscapeAnalysis -server

输出

可见 TLAB 可以加速对象分配

注意:

TLAB 一般空间不会太大,很容易装满,如果一个 100KB 的空间,已经使用了 80KB,当需要再分配一个 30KB 的对象时,虚拟机有 2 种选择,第一:废弃当前 TLAB,浪费 20KB 空间;第二:将 30KB 对象直接分配到堆上,保留当前 TLAB,将来有小于 20KB 的对象直接使用此块空间。虚拟机根据 refill_waste的值,当请求对象大于 refill_waste,会在堆中分配,小于则废弃 当前TLAB,新建 TLAB 分配新对象,这个阈值由 TLABRefillWasteFraction调整,默认值是 64,代表 1/64的 TLAB 空间作为 refill_waste

开启 TLAB 跟踪详情(-XX:+PrintTLAB)

-XX:+UseTLAB -server -XX:+PrintTLAB -XX:+PrintGC -XX:TLABSize=102400 -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=100 -XX:-DoEscapeAnalysis

-XX:TLABSize 代表分配 TLAB 大小,

输出

TLAB: gc thread: 0x00007f943804c800 [id: 11523] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 9.76562 5000KB refills: 1 waste 98.9% gc: 101296B slow: 0B fast: 0B
TLAB: gc thread: 0x00007f9439001800 [id: 9987] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 9.76562 5000KB refills: 5 waste 0.1% gc: 0B slow: 488B fast: 0B
TLAB totals: thrds: 2 refills: 6 max: 5 slow allocs: 0 max 0 waste: 16.6% gc: 101296B max: 101296B slow: 488B max: 488B fast: 0B max: 0B
[GC (Allocation Failure) 512K->352K(130560K), 0.0012200 secs]
TLAB: gc thread: 0x00007f9438034000 [id: 18179] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 9.76562 5000KB refills: 1 waste 99.7% gc: 102080B slow: 0B fast: 0B
TLAB: gc thread: 0x00007f9438046800 [id: 20483] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 9.76562 5000KB refills: 1 waste 100.0% gc: 102384B slow: 0B fast: 0B
TLAB: gc thread: 0x00007f9439001800 [id: 9987] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 5.37109 2750KB refills: 4 waste 0.0% gc: 0B slow: 120B fast: 0B
TLAB totals: thrds: 3 refills: 6 max: 4 slow allocs: 0 max 0 waste: 33.3% gc: 204464B max: 102384B slow: 120B max: 120B fast: 0B max: 0B
[GC (Allocation Failure) 864K->528K(131072K), 0.0007710 secs]
TLAB: gc thread: 0x00007f9439001800 [id: 9987] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 3.76465 3855KB refills: 13 waste 0.0% gc: 0B slow: 72B fast: 16B
TLAB totals: thrds: 1 refills: 13 max: 13 slow allocs: 0 max 0 waste: 0.0% gc: 0B max: 0B slow: 72B max: 72B fast: 16B max: 16B
[GC (Allocation Failure) 1552K->544K(131072K), 0.0006530 secs]
TLAB: gc thread: 0x00007f9439001800 [id: 9987] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 2.89136 2961KB refills: 13 waste 0.0% gc: 0B slow: 40B fast: 8B
TLAB totals: thrds: 1 refills: 13 max: 13 slow allocs: 0 max 0 waste: 0.0% gc: 0B max: 0B slow: 40B max: 40B fast: 8B max: 8B
[GC (Allocation Failure) 1568K->560K(132096K), 0.0006120 secs]
TLAB: gc thread: 0x00007f9439001800 [id: 9987] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 2.32372 4759KB refills: 23 waste 0.0% gc: 0B slow: 40B fast: 8B
TLAB totals: thrds: 1 refills: 23 max: 23 slow allocs: 0 max 0 waste: 0.0% gc: 0B max: 0B slow: 40B max: 40B fast: 8B max: 8B
[GC (Allocation Failure) 2608K->584K(132096K), 0.0005550 secs]
TLAB: gc thread: 0x00007f9439001800 [id: 9987] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 1.90348 3898KB refills: 21 waste 0.0% gc: 0B slow: 40B fast: 0B
TLAB totals: thrds: 1 refills: 21 max: 21 slow allocs: 0 max 0 waste: 0.0% gc: 0B max: 0B slow: 40B max: 40B fast: 0B max: 0B
[GC (Allocation Failure) 2632K->584K(134656K), 0.0005630 secs]
TLAB: gc thread: 0x00007f9439001800 [id: 9987] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 1.59615 6538KB refills: 41 waste 0.0% gc: 0B slow: 664B fast: 0B
TLAB totals: thrds: 1 refills: 41 max: 41 slow allocs: 0 max 0 waste: 0.0% gc: 0B max: 0B slow: 664B max: 664B fast: 0B max: 0B
[GC (Allocation Failure) 4680K->653K(134656K), 0.0005840 secs]
TLAB: gc thread: 0x00007f9439001800 [id: 9987] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 1.38784 5685KB refills: 41 waste 0.0% gc: 0B slow: 664B fast: 0B
TLAB totals: thrds: 1 refills: 41 max: 41 slow allocs: 0 max 0 waste: 0.0% gc: 0B max: 0B slow: 664B max: 664B fast: 0B max: 0B
[GC (Allocation Failure) 4749K->573K(138752K), 0.0002190 secs]
TLAB: gc thread: 0x00007f9439001800 [id: 9987] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 1.25244 10260KB refills: 82 waste 0.0% gc: 0B slow: 1328B fast: 0B
TLAB totals: thrds: 1 refills: 82 max: 82 slow allocs: 0 max 0 waste: 0.0% gc: 0B max: 0B slow: 1328B max: 1328B fast: 0B max: 0B
[GC (Allocation Failure) 8765K->573K(138752K), 0.0002610 secs]
TLAB: gc thread: 0x00007f9439001800 [id: 9987] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 1.16443 9539KB refills: 82 waste 0.0% gc: 0B slow: 1328B fast: 0B
TLAB totals: thrds: 1 refills: 82 max: 82 slow allocs: 0 max 0 waste: 0.0% gc: 0B max: 0B slow: 1328B max: 1328B fast: 0B max: 0B
[GC (Allocation Failure) 8765K->573K(143872K), 0.0002220 secs]
TLAB: gc thread: 0x00007f9439001800 [id: 9987] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 1.10722 14739KB refills: 134 waste 0.0% gc: 0B slow: 2152B fast: 0B
TLAB totals: thrds: 1 refills: 134 max: 134 slow allocs: 0 max 0 waste: 0.0% gc: 0B max: 0B slow: 2152B max: 2152B fast: 0B max: 0B
[GC (Allocation Failure) 13885K->573K(143872K), 0.0003430 secs]
TLAB: gc thread: 0x00007f9439001800 [id: 9987] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 1.07201 14271KB refills: 134 waste 0.0% gc: 0B slow: 2152B fast: 0B
TLAB totals: thrds: 1 refills: 134 max: 134 slow allocs: 0 max 0 waste: 0.0% gc: 0B max: 0B slow: 2152B max: 2152B fast: 0B max: 0B
[GC (Allocation Failure) 13885K->573K(152064K), 0.0002860 secs]
TLAB: gc thread: 0x00007f9439001800 [id: 9987] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 1.04912 22560KB refills: 215 waste 0.0% gc: 0B slow: 3456B fast: 0B
TLAB totals: thrds: 1 refills: 215 max: 215 slow allocs: 0 max 0 waste: 0.0% gc: 0B max: 0B slow: 3456B max: 3456B fast: 0B max: 0B
[GC (Allocation Failure) 22077K->573K(152064K), 0.0003170 secs]
TLAB: gc thread: 0x00007f9439001800 [id: 9987] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 1.03186 22189KB refills: 215 waste 0.0% gc: 0B slow: 3456B fast: 0B
TLAB totals: thrds: 1 refills: 215 max: 215 slow allocs: 0 max 0 waste: 0.0% gc: 0B max: 0B slow: 3456B max: 3456B fast: 0B max: 0B
[GC (Allocation Failure) 22077K->573K(165376K), 0.0007820 secs]
TLAB: gc thread: 0x00007f9439001800 [id: 9987] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 1.02064 35535KB refills: 349 waste 0.0% gc: 0B slow: 5584B fast: 0B
TLAB totals: thrds: 1 refills: 349 max: 349 slow allocs: 0 max 0 waste: 0.0% gc: 0B max: 0B slow: 5584B max: 5584B fast: 0B max: 0B
[GC (Allocation Failure) 35389K->573K(165376K), 0.0003020 secs]
TLAB: gc thread: 0x00007f9439001800 [id: 9987] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 1.01426 35313KB refills: 349 waste 0.0% gc: 0B slow: 5584B fast: 0B
TLAB totals: thrds: 1 refills: 349 max: 349 slow allocs: 0 max 0 waste: 0.0% gc: 0B max: 0B slow: 5584B max: 5584B fast: 0B max: 0B
[GC (Allocation Failure) 35389K->573K(186368K), 0.0002460 secs]
TLAB: gc thread: 0x00007f9439001800 [id: 9987] desired_size: 100KB slow allocs: 0 refill waste: 1024B alloc: 1.01012 56373KB refills: 558 waste 0.0% gc: 0B slow: 8936B fast: 0B
TLAB totals: thrds: 1 refills: 558 max: 558 slow allocs: 0 max 0 waste: 0.0% gc: 0B max: 0B slow: 8936B max: 8936B fast: 0B max: 0B
[GC (Allocation Failure) 56381K->573K(186368K), 0.0003230 secs]

说明:

desired_size 为 TLAB 大小,通过 -XX:TLABSize=102400=100KB 设置,slow allocs 代表从上一次新生代 GC 到现在慢回收的次数(TLAB 空闲空间因为太小,导致将大对象分配到堆上的情况),

原文  http://mousycoder.com/thinking-in-jvm/37/
正文到此结束
Loading...