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参数值一致
    • (对于直接内存有大小限制,我的理解是这个区域还是要向系统申请的,不是系统剩下多少就能用多少)
相关推荐
请你打开电视看看2 小时前
Jvm知识点
jvm
程序猿进阶3 小时前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
阿龟在奔跑14 小时前
引用类型的局部变量线程安全问题分析——以多线程对方法局部变量List类型对象实例的add、remove操作为例
java·jvm·安全·list
王佑辉15 小时前
【jvm】方法区常用参数有哪些
jvm
王佑辉15 小时前
【jvm】HotSpot中方法区的演进
jvm
Domain-zhuo15 小时前
什么是JavaScript原型链?
开发语言·前端·javascript·jvm·ecmascript·原型模式
Theodore_10222 天前
7 设计模式原则之合成复用原则
java·开发语言·jvm·设计模式·java-ee·合成复用原则
我是苏苏2 天前
Web开发:ORM框架之使用Freesql的DbFrist封装常见功能
java·前端·jvm
天草二十六_简村人2 天前
Java语言编程,通过阿里云mongo数据库监控实现数据库的连接池优化
java·jvm·数据库·mongodb·阿里云·微服务·云计算
老码沉思录2 天前
Android开发实战班 - 数据持久化 - Room 数据库应用
android·jvm·数据库