JVM13-内存分配

堆内存分配方式,分配规则

- Java堆内存区域的划分以及作用

- 对象分配的规则有哪些

  * 对象主要分配在新生代的 Eden 区上
  * 如果启动了本地线程分配缓冲,将按线程优先在 TLAB 上分配
  * 少数情况下也可能会直接分配在老年代中

- GC参数指定垃圾回收

  * -Xms20 M、-Xmx20 M、-Xmn1 0 M 这 3 个参数限制了 Java 堆大小为 20 MB,不可扩展,其中 10 MB 分配给新生代,剩下的 10 MB 分配给老年代。-Xx: SurvivorRatio= 8 决定了新生代中 Eden 区与两个 Survivor 区的空间比例是 8:1

- 新生代与老年代

  * 新生代 GC (Minor GC):指发生在新生代的垃圾收集动作,因为 Java 对象大多都具备朝生夕灭的特性,所以 Minor GC 非常频繁,一般回收速度老年代 GC (Major GC/ Full GC):指发生在老年代的 GC,出现了 Major GC,经常会伴随至少一次的 Minor GC(但非绝对的,在 Parallel Scavenge 收集器的收集策略里就有直接进行 Major GC 的策略选择过程)。Major GC 的速度一般会比 Minor GC 慢 10 倍以上。

public class TestJVMFirst {


    private static final int byteSize = 1024*1024;

    public static void main(String[] args) {
        byte[] bytes1 = new byte[2*byteSize];
        byte[] bytes2= new byte[4*byteSize];
        byte[] bytes3 = new byte[5*byteSize];
    }

}

 

 

堆内存JVM参数讲解,大对象分配原则讲解和代码验证 

- 是什么?

  * 所谓的大对象是指,需要大量连续内存空间的 Java 对象,最典型的大对象就是那种很长的字符串以及数组

  * 虚拟机提供了一个-XX: PretenureSizeThreshold 参数,令大于这个设置值的对象直接在老年代分配。这样做的目的是避免在 Eden 区及两个 Survivor 区之间发生大量的内存复制

- 实战代码演练大对象配置

  * -verbose:gc -XX:+PrintGCDetails 开启GC日志打印

  * -Xms20 M 设置JVM初始内存为20M

  * -Xmx20 M 设置JVM最大内存为20M

  * -Xmn10 M 设置年轻代内存大小为10M

 

```shell
-verbose:gc -XX:+PrintGCDetails -XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:PretenureSizeThreshold=3145728
```

public class TestMaxObject {


    public static void main(String[] args) {
        byte[] bytes = new byte[1024*1024*2];
    }
}

 

逃逸分析和栈上分配

 

- 逃逸分析

  * 逃逸分析的基本行为就是分析对象动态作用域:当一个对象在方法中被定义后,它可能被外部方法所引用,称为方法逃逸。甚至还有可能被外部线程访问到,譬如赋值给类变量或可以在其他线程中访问的实例变量,称为线程逃逸

- 栈上分配

  * 栈上分配就是把方法中的变量和对象分配到栈上,方法执行完后自动销毁,而不需要垃圾回收的介入,从而提高系统性能

-XX:+DoEscapeAnalysis开启逃逸分析(jdk1.8默认开启,其它版本未测试)
-XX:-DoEscapeAnalysis 关闭逃逸分析

public class TestEscape {

    public static  Object obj ;

    public void variableEscape(){
        obj = new Object();     //发生逃逸
    }

    public Object methodEscape(){
        return new Object();   //方法逃逸
    }

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

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

}

 

posted @ 2019-07-17 15:24  valar-dohaeris  阅读(174)  评论(0)    收藏  举报