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

目录

概述

相关文章在此总结如下:

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

对象的创建流程


常量池检查: 检查 new 指令是否能在 常量池中定位到这个类的符号引用,检查类之前是否被加载过。

分配内存空间:

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

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

对象的内存分配方式

内存分配的方法有两种:

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

对象怎样才会进入老年代


空间担保机制: 当新生代无法分配内存的时候,要想将新生代的对象转移至老年代,然后将新对象放入腾空的新生代。此种机制称之为内存担保

对象进入老年代如下:

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

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

大对象直接进入老年代

测试代码如下:

java 复制代码
/**
 * -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];
    }
}
bash 复制代码
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

内存担保

测试代码如下:

java 复制代码
/**
 * 内存分配担保案例
 */
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("完毕");
    }
}
bash 复制代码
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$ 


当新生代无法分配内存的时候,要想将新生代的对象转移至老年代,然后将新对象放入腾空的新生代。

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

bash 复制代码
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

bash 复制代码
java -XX:+PrintCommandLineFlags -version

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

bash 复制代码
java -XX:+PrintFlagsFinal -version | grep 'bool Use' | grep 'GC ' | grep -v java

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

bash 复制代码
jhsdb jmap --heap --pid 22397

结束

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

相关推荐
Ysjt | 深5 小时前
C++多线程编程入门教程(优质版)
java·开发语言·jvm·c++
阿伟*rui12 小时前
jvm入门
jvm
学点东西吧.15 小时前
JVM(五、垃圾回收器)
jvm
请你打开电视看看18 小时前
Jvm知识点
jvm
程序猿进阶18 小时前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
阿龟在奔跑1 天前
引用类型的局部变量线程安全问题分析——以多线程对方法局部变量List类型对象实例的add、remove操作为例
java·jvm·安全·list
王佑辉1 天前
【jvm】方法区常用参数有哪些
jvm
王佑辉1 天前
【jvm】HotSpot中方法区的演进
jvm
Domain-zhuo1 天前
什么是JavaScript原型链?
开发语言·前端·javascript·jvm·ecmascript·原型模式
Theodore_10222 天前
7 设计模式原则之合成复用原则
java·开发语言·jvm·设计模式·java-ee·合成复用原则