6.jvm中对象创建流程与内存分配

目录

  • 概述
  • 对象的创建流程
  • 对象的内存分配方式
    • 对象怎样才会进入老年代
      • 大对象直接进入老年代
      • 内存担保
  • jvc 相关指令
    • 查看jdk默认使用的gc
    • 查看当前jdk支持的有哪些gc
    • 查看指定进程当前正在使用的gc
  • 结束

概述

相关文章在此总结如下:

文章 地址
jvm基本知识 地址
jvm类加载系统 地址
双亲委派模型与打破双亲委派 地址
运行时数据区 地址
运行时数据区-字符串常量池、程序计数器、直接内存 地址

对象的创建流程

6.jvm中对象创建流程与内存分配_第1张图片
常量池检查: 检查 new 指令是否能在 常量池中定位到这个类的符号引用,检查类之前是否被加载过。

分配内存空间:

  • 指针碰撞:GC 不带压缩功能,Serial和ParNew
  • 空闲列表:GC 带压缩功能,CMS

必要信息设置: 对象类的元数据、对象哈希码、GC分代年龄 —> 对象头

对象的内存分配方式

内存分配的方法有两种:

  • 指针碰撞 (Bump the Pointer)
  • 空间列表 (Free List)
分配方法 说明 收集器
指针碰撞(Bump the Pointer) 内存地址是连续的(新生代) Serial和ParNew收集器
空闲列表(Free List) 内存地址不连续(老年代) CMS收集器和Mark-Sweep收集器

6.jvm中对象创建流程与内存分配_第2张图片

对象怎样才会进入老年代

6.jvm中对象创建流程与内存分配_第3张图片
空间担保机制: 当新生代无法分配内存的时候,要想将新生代的对象转移至老年代,然后将新对象放入腾空的新生代。此种机制称之为内存担保

对象进入老年代如下:

  • 新对象大多数默认都进入 Eden
  • 对象进入老年代的四种情况
    • 年龄太大 MinorGC15 [-XX:MaxTenuringThreshold]
    • 动态年龄判断:MinorGC后会动态判断年龄,将符合要求对象番移入老年代
    • 大对象直接进入老年代 1M [-XX:PretenureSizeThreshold]
    • MinorGC后存活对象太多无法放入 Survivor

动态年龄判断:例子,Survivor 区中有一批对象,年龄分别为 年龄1+年龄2+年龄n的多个对象,对象总和大小超过了Survivor区域的 50%,此时就会将年龄n及以上的对象都放入老年代。

大对象直接进入老年代

测试代码如下:

/**
 * -XX:NewRatio=2 新生代与老年代比值
 * -XX:SurvivorRatio=8  新生代中,Eden 与两个Survivor 区域比值
 * -XX:+PrintGcDetails  打印详细 GC 日志
 * -XX:PretenureSizeThreshold  对象超过多大值直接在老年代分配,默认值为0,不限制
 */
public class YoungOldArea {
    public static void main(String[] args) {
        // 分配 20M
        byte[] bytes = new byte[1024 * 1024 * 20];
    }
}
appledeMacBook-Pro:gc hyl$ javac /Users/hyl/Desktop/jk/jvm/YoungOldArea.java 
appledeMacBook-Pro:gc hyl$ cd /Users/hyl/Desktop/jk/jvm
appledeMacBook-Pro:jvm hyl$ java  -Xmx60m -Xms60m -XX:NewRatio=2  -XX:SurvivorRatio=8 -XX:+PrintGCDetails YoungOldArea

6.jvm中对象创建流程与内存分配_第4张图片

内存担保

测试代码如下:

/**
 * 内存分配担保案例
 */
public class MemoryAllocationGuarantee {

    private static final int _1MB = 1024 * 1024;

    public static void main(String[] args) {
        memoryAllocation();
    }

    public static void memoryAllocation() {

        byte[] allocation1, allocation2, allocation3, allocation4;
        allocation1 = new byte[1 * _1MB];
        allocation2 = new byte[1 * _1MB];
        allocation3 = new byte[1 * _1MB];
        allocation4 = new byte[5 * _1MB];
        System.out.println("完毕");
    }
}
appledeMacBook-Pro:jvm hyl$ javac MemoryAllocationGuarantee.java
appledeMacBook-Pro:jvm hyl$ ls
MemoryAllocationGuarantee.class	MemoryAllocationGuarantee.java	YoungOldArea.class		YoungOldArea.java		lib
appledeMacBook-Pro:jvm hyl$ java  -Xmx20m -Xms20m -XX:NewRatio=2  -XX:SurvivorRatio=8  -XX:+UseSerialGC   -XX:+PrintGCDetails MemoryAllocationGuarantee
[GC (Allocation Failure) [DefNew: 3749K->279K(6144K), 0.0039312 secs] 3749K->3351K(19840K), 0.0039781 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
完毕
Heap
 def new generation   total 6144K, used 5561K [0x00000007bec00000, 0x00000007bf2a0000, 0x00000007bf2a0000)
  eden space 5504K,  95% used [0x00000007bec00000, 0x00000007bf128920, 0x00000007bf160000)
  from space 640K,  43% used [0x00000007bf200000, 0x00000007bf245d48, 0x00000007bf2a0000)
  to   space 640K,   0% used [0x00000007bf160000, 0x00000007bf160000, 0x00000007bf200000)
 tenured generation   total 13696K, used 3072K [0x00000007bf2a0000, 0x00000007c0000000, 0x00000007c0000000)
   the space 13696K,  22% used [0x00000007bf2a0000, 0x00000007bf5a0030, 0x00000007bf5a0200, 0x00000007c0000000)
 Metaspace       used 2668K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 287K, capacity 386K, committed 512K, reserved 1048576K
appledeMacBook-Pro:jvm hyl$ 

6.jvm中对象创建流程与内存分配_第5张图片
当新生代无法分配内存的时候,要想将新生代的对象转移至老年代,然后将新对象放入腾空的新生代。

注意: jdk8 设置了 使用 SerialGC ,默认GC不是这样的流程,如下命令行执行的命令

appledeMacBook-Pro:jvm hyl$ java  -Xmx20m -Xms20m -XX:NewRatio=2  -XX:SurvivorRatio=8   -XX:+PrintGCDetails MemoryAllocationGuarantee
完毕
Heap
 PSYoungGen      total 6144K, used 3764K [0x00000007bf980000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 5632K, 66% used [0x00000007bf980000,0x00000007bfd2d180,0x00000007bff00000)
  from space 512K, 0% used [0x00000007bff80000,0x00000007bff80000,0x00000007c0000000)
  to   space 512K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007bff80000)
 ParOldGen       total 13824K, used 5120K [0x00000007bec00000, 0x00000007bf980000, 0x00000007bf980000)
  object space 13824K, 37% used [0x00000007bec00000,0x00000007bf100010,0x00000007bf980000)
 Metaspace       used 2668K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 287K, capacity 386K, committed 512K, reserved 1048576K

在这里插入图片描述

jvc 相关指令

查看jdk默认使用的gc

java -XX:+PrintCommandLineFlags -version

查看当前jdk支持的有哪些gc

java -XX:+PrintFlagsFinal -version | grep 'bool Use' | grep 'GC ' | grep -v java

查看指定进程当前正在使用的gc

jhsdb jmap --heap --pid 22397

结束

至此,jvm中对象创建流程与内存分配就结束了,如有疑问,欢迎评论区留言。

你可能感兴趣的:(jvm,jvm,创建对象流程,内存分配)