• Java中对象在内存中的大小、分配等问题


    Java创建一个对象的过程

    1. 是否对象指向的类已经加载到内存了
      1. 如果没有加载,就要经过load、linking(verification、preparation、resolution)、initializing把类加载进内存中。
    2. 为对象分配内存空间、成员变量赋默认值
    3. 执行构造方法
      1. 成员变量赋指定值
      2. 执行构造方法语句

    对象在内存中的存储布局(这里指在64位的JVM中)

    普通对象

    1. 对象头:
      1. markwork 8个字节
      2. ClassPointer指针 JVM默认开启了 -XX:userCompressedClassPoniters参数,把ClassPointer指针从8个字节压缩到4个字节
    2. 实例数据
      1. 引用类型 JVM默认开启了 -XX:userCompressedOops参数,把原本普通引用类型指针从8个字节压缩到4个字节
    3. Padding对齐,将对象大小对齐到8的倍数

    数组

    1. 对象头:
      1. markword 8个字节
      2. ClassPointer指针 (如上)
      3. 数组大小 4个字节
    2. 数组数据
    3. Padding 对齐到8个字节

    markword具体包括什么

    1. 上图中指的是在32位JVM虚拟机中,在64为JVM虚拟机中hashcode占了31位,另外有25位没用过,有一位是没用的,其他都一样
    2. hashcode只有在对象调用了hashcode方法才会计算出hashCode,并把值存入里面。另外需要注意的是,在调用hashCode之后,该对象就不能进入偏向锁,因为偏向锁中需要记录线程ID,和线程重入次数(Epoch),但是他们位置被hashCode占了
    3. JVM中默认GC年龄最大为15,是因为如果所示,分代年龄只有4位,最大表示15。

    对象如何定位

    1. 通过句柄池

      ​ 使用句柄池最大的好处是reference存储的是稳定的句柄池地址,在因为GC之后对象被移动了只需要改变句柄池中指向实例数据的地址。

    2. 通过直接指针

      ​ 使用直接指针访问的好处是速度更快,节省了一次指针定位的时间开销,就虚拟机HotSpot而言,它主要使用第二种方式进行对象访问。但是当对象因为GC而被移动位置后,所用指向这个对象的引用都要改变引用地址。

  • 相关阅读:
    smarty对网页性能的影响
    php-fpm正在生成页面时,浏览器刷新后,php-fpm会退出吗?
    为什么日志记录到别的目录了?
    一个空格引发的bug
    linux内核--页高速缓存
    radix树
    linux内核--用户态内存管理
    linux内核--内核内存管理
    linux内核--软中断与tasklet
    linux内核--几个上下文(context)
  • 原文地址:https://www.cnblogs.com/zcr-xiaozhai/p/13816054.html
Copyright © 2020-2023  润新知