JVM 第二部分-3(对象,直接内存)

对象

  • 对象的实例化
    • 创建对象的方式
      • new 对象
        • 变形1:使用类的静态方法获得对象
        • 变形2:xxxBuilder、xxxFactory的静态方法
      • 反射
        • Class的newInstance():反射的方式,只能调用空参的构造器,权限必须是public
        • Constructor的newInstance(xxx):反射的方式,可以调用空参,带参的构造器,权限没有要求
      • 使用clone():不调用任何构造器,当前类需要实现Cloneable接口,实现clone()
      • 使用反序列化:从文件、网络中获取一个对象的二进制流
      • 第三方库:Objenesis
    • 创建对象的步骤:
      • 1.对象对应的类加载、链接、初始化
      • 2.为对象分配内存(这个阶段就可以确定对象的大小)
        • 如果内存规整------指针碰撞(就是用一个指针指向内存已占用和未占用区域的分界线)
        • 如果内存不规整------就是还在用的区域和没有用的区域混杂在一起------虚拟机要维护一个列表------空闲列表分配------记下没有使用的区域
        • 一般是带有整理功能的虚拟机才会内存规整
      • 3.处理并发问题
        • 采用CAS+失败重试保证更新的原子性
        • 每个线程预先分配一块TLAB
      • 4.初始化分配到的空间------所有属性设默认值(零值),保证对象实例字段在不赋值时可以直接使用
      • 5.设置对象的对象头(将对象的所属类,即类的元数据信息、对象的HashCode和对象的GC信息、锁信息等数据结构储存在对象的对象头中。这个过程的具体设置方式取决于jvm的实现)
      • 6.执行init方法进行初始化(属性的显式初始化,代码块中初始化,构造器中初始化)
  • 对象的内存分配
    • 对象头(Header)
      • 运行时元数据
        • 哈希值
        • GC分代年龄
        • 锁状态标志
        • 线程持有的锁
        • 偏向线程ID
        • 偏向时间戳
      • 类型指针------指向类元数据InstanceKlass,确定该对象所属的类型
      • 如果是数组,还需要记录数组的长度
    • 实例数据(Instance Data)
      • 说明:它是对象真正存储的有效信息,包括程序代码中定义的各种类型的字段(包括从父类继承下来的和本身拥有的字段)
      • 规则:
        • 相同宽度的字段总是被分配在一起
        • 父类中定义的变量会出现在子类之前
        • 如果CompactFields参数为true(默认为true):子类的窄变量可能插入到父类变量的空隙
    • 对齐填充(Padding)(不是必须的,也没什么特别含义,就是用来占位的)
  • 对象的访问定位
    • 句柄访问
      • 好处是 对象移动之后(标量替换,垃圾回收都会移动类),栈里面的变量不用改,很稳定
      • 缺点是需要开辟额外空间,也不是一步到位地找到
    • 直接引用(Hotspot采用)
      • 好处是一步到位,不用开辟额外空间

直接内存

  • 它是在Java堆外的、直接向系统申请的内存区间
  • 不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域
  • 所有用Java的内存分析工具,比如jvisualvm,JProfiler等,是看不出元空间,或者说是直接内存的大小的
    • 程序产生的dump文件也看不到。所以,如果程序发生OOM,dump文件又比较小,有可能是涉及到NIO,直接内存的问题
  • 来源于NIO,通过存在堆中的DirectByteBuffer操作Native内存
  • 访问直接内存的速度会优于Java堆,即读写性能高
    • 读写频繁的场合可以用直接内存
    • Java的NIO库允许Java程序使用直接内存,用于数据缓冲区
  • 也是有可能会OOM的,因为它受限于系统能给内存,并不是无限大。特别是当设置堆的内存特别大,导致剩下的内存不够的时候,就容易OOM
  • 缺点
    • 分配回收成本较高
    • 不受jvm内存回收管理
  • 直接内存大小可以通过MaxDirectMemorySize设置
  • 如果不指定,默认与堆的最大值-Xmx参数值一致
    • (对于直接内存有大小限制,我的理解是这个区域还是要向系统申请的,不是系统剩下多少就能用多少)
相关推荐
yuanbenshidiaos6 小时前
c++---------数据类型
java·jvm·c++
java1234_小锋9 小时前
JVM对象分配内存如何保证线程安全?
jvm
40岁的系统架构师12 小时前
1 JVM JDK JRE之间的区别以及使用字节码的好处
java·jvm·python
寻找沙漠的人12 小时前
理解JVM
java·jvm·java-ee
我叫啥都行13 小时前
计算机基础复习12.22
java·jvm·redis·后端·mysql
bufanjun00115 小时前
JUC并发工具---ThreadLocal
java·jvm·面试·并发·并发基础
东阳马生架构1 天前
JVM简介—1.Java内存区域
jvm
工程师老罗1 天前
Android笔试面试题AI答之SQLite(2)
android·jvm·sqlite
Qzer_4071 天前
jvm字节码中方法的结构
jvm
奇偶变不变2 天前
RTOS之事件集
java·linux·jvm·单片机·算法