对象的创建过程包括以下几个步骤:申请内存空间、赋予默认值、设置初始值。在这个过程中,可能会发生指令重排,导致对象处于半初始化状态。这也是为什么在dcl(双重检查锁定)单例模式中需要使用volatile关键字的原因,因为new操作可能会出现问题。
存储器的层次结构如图所示:
硬件层的数据一致性协议有很多种,其中Intel使用的是MESI协议。
现代CPU的数据一致性是通过缓存锁(如MESI等)和总线锁来实现的。读取缓存是以cache line为基本单位,目前是64字节。如果同一缓存行的两个不同数据被两个不同CPU锁定,会产生互相影响的伪共享问题。使用缓存行的对齐可以提高效率,如disruptor框架所利用的。
立即学习“Java免费学习笔记(深入)”;
乱序问题(读):CPU为了提高效率,如果没有直接依赖关系,会在一条指令执行的过程中(读数据慢100倍)同时执行另一条指令。写操作也可以进行合并,放在WCBuffer(4个位置)中执行。
案例:
package com.mashibing.juc.c_029_WriteCombining; public final class WriteCombining { private static final int ITERATIONS = Integer.MAX_VALUE; private static final int ITEMS = 1; // ... }
为了保证特定情况下不发生乱序,JVM使用内存屏障来确保有序性。硬件层面上的实现不一定依赖硬件级别的内存屏障,还可以依赖硬件级别的lock指令。
硬件CPU内存屏障包括:
JVM级别如何规范(JSR133):
volatile的实现细节:
synchronized的实现细节:
对象的创建过程:
class loading
class linking(verification, preparation, resolution)
class initializing
申请对象内存
成员变量赋默认值
调用构造方法
成员变量顺序赋初始值
执行构造方法语句
对象在内存的存储布局:
首先查看自己虚拟机的配置:java -XX:+PrintCommandLinesFlags -version
红色的参数就是内存布局
对象的内容(对象的内存布局也可以这么说):
普通对象:
数组对象:
首先一个class load到内存的时候有一个agent来截获或修改,需要自己实现它(premain方法),相当于代理。
实验:
package com.mashibing.jvm.agent; import java.lang.instrument.Instrumentation; <p>public class ObjectSizeAgent { private static Instrumentation inst;</p><pre class="brush:php;toolbar:false">public static void premain(String agentArgs, Instrumentation _inst) { inst = _inst; } public static long sizeOf(Object o) { return inst.getObjectSize(o); }
}
Manifest-Version: 1.0 Created-By: mashibing.com Premain-Class: com.mashibing.jvm.agent.ObjectSizeAgent
注意Premain-Class这行必须是新的一行(回车 + 换行),确认IDEA不能有任何错误提示。
-javaagent:C:\work\ijprojects\ObjectSize\out\artifacts\ObjectSize_jar\ObjectSize.jar
package com.mashibing.jvm.c3_jmm;</p><p>import com.mashibing.jvm.agent.ObjectSizeAgent;</p><p>public class T03_SizeOfAnObject { public static void main(String[] args) { System.out.println(ObjectSizeAgent.sizeOf(new Object())); System.out.println(ObjectSizeAgent.sizeOf(new int[] {})); System.out.println(ObjectSizeAgent.sizeOf(new P())); }</p><pre class="brush:php;toolbar:false">private static class P { // 8 _markword // 4 _oop指针 int id; // 4 String name; // 4 int age; // 4 byte b1; // 1 byte b2; // 1 Object o; // 4 byte b3; // 1 }
}
Object 16字节
Int 16字节
Hotspot开启内存压缩的规则(64位机):
对象头具体包含什么:
具体看对象的状态
当一个对象计算过identityHashCode之后,不能进入偏向锁状态。
以上就是让你吊打面试官的Java内存结构以及对象的内容讲解的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号