0

0

让你吊打面试官的Java内存结构以及对象的内容讲解

星夢妙者

星夢妙者

发布时间:2025-04-26 13:42:01

|

278人浏览过

|

来源于php中文网

原创

对象的创建过程包括以下几个步骤:申请内存空间、赋予默认值、设置初始值。在这个过程中,可能会发生指令重排,导致对象处于半初始化状态。这也是为什么在dcl(双重检查锁定)单例模式中需要使用volatile关键字的原因,因为new操作可能会出现问题。

存储器的层次结构如图所示:

让你吊打面试官的Java内存结构以及对象的内容讲解

硬件层的数据一致性协议有很多种,其中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内存屏障包括:

  • sfence:在sfence指令前的写操作必须在sfence指令后的写操作前完成。
  • lfence:在lfence指令前的读操作必须在lfence指令后的读操作前完成。
  • mfence:在mfence指令前的读写操作必须在mfence指令后的读写操作前完成。

JVM级别如何规范(JSR133):

  • LoadLoad屏障:对于语句Load1; LoadLoad; Load2,确保在Load2及后续读取操作访问数据前,Load1要读取的数据被读取完毕。
  • StoreStore屏障:对于语句Store1; StoreStore; Store2,确保在Store2及后续写入操作执行前,Store1的写入操作对其它处理器可见。
  • LoadStore屏障:对于语句Load1; LoadStore; Store2,确保在Store2及后续写入操作被刷出前,Load1要读取的数据被读取完毕。
  • StoreLoad屏障:对于语句Store1; StoreLoad; Load2,确保在Load2及后续所有读取操作执行前,Store1的写入对所有处理器可见。

volatile的实现细节:

  1. 字节码层面:ACC_VOLATILE
  2. JVM层面:Volatile内存区的读写都加屏障
    • StoreStoreBarrier
    • volatile 写操作
    • StoreLoadBarrier
    • LoadLoadBarrier
    • volatile 读操作
    • LoadStoreBarrier
  3. OS和硬件层面:使用lock指令实现(如在Windows上)或MESI协议。

synchronized的实现细节:

  1. 字节码层面:ACC_SYNCHRONIZED,monitorenter和monitorexit(两个)
  2. JVM层面:C++调用了操作系统提供的同步机制
  3. OS和硬件层面:在X86上使用lock cmpxchg指令

对象的创建过程:

  1. class loading

  2. class linking(verification, preparation, resolution)

  3. class initializing

  4. 申请对象内存

  5. 成员变量赋默认值

  6. 调用构造方法<init></init>

    成员变量顺序赋初始值

    执行构造方法语句

    Q.AI视频生成工具
    Q.AI视频生成工具

    支持一分钟生成专业级短视频,多种生成方式,AI视频脚本,在线云编辑,画面自由替换,热门配音媲美真人音色,更多强大功能尽在QAI

    下载

对象在内存的存储布局:

首先查看自己虚拟机的配置:java -XX:+PrintCommandLinesFlags -version

红色的参数就是内存布局

让你吊打面试官的Java内存结构以及对象的内容讲解

对象的内容(对象的内存布局也可以这么说):

普通对象:

  1. 对象头markword(8字节)
  2. ClassPointer指针(-XX:+UseCompressedClassPointers为4字节,不开启为8字节)
  3. 实例数据引用类型(-XX:+UseCompressedOops为4字节,不开启为8字节,Oops = Ordinary Object Pointers)
  4. Padding对齐(8的倍数)

数组对象:

  1. 对象头markword(8字节)
  2. ClassPointer指针(-XX:+UseCompressedClassPointers为4字节,不开启为8字节)
  3. 数组长度(4字节)
  4. 数组数据
  5. 对齐(8的倍数)

首先一个class load到内存的时候有一个agent来截获或修改,需要自己实现它(premain方法),相当于代理。

实验:

  1. 新建项目ObjectSize(1.8)
  2. 创建文件ObjectSizeAgent
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;"><code>public static void premain(String agentArgs, Instrumentation _inst) {
    inst = _inst;
}

public static long sizeOf(Object o) {
    return inst.getObjectSize(o);
}

}

  1. 在src目录下创建META-INF/MANIFEST.MF
<code>Manifest-Version: 1.0
Created-By: mashibing.com
Premain-Class: com.mashibing.jvm.agent.ObjectSizeAgent</code>

注意Premain-Class这行必须是新的一行(回车 + 换行),确认IDEA不能有任何错误提示。

  1. 打包jar文件
  2. 在需要使用该AgentJar的项目中引入该Jar包(project structure - project settings - library 添加该jar包)
  3. 运行时需要该AgentJar的类,加入参数:
<code>-javaagent:C:\work\ijprojects\ObjectSize\out\artifacts\ObjectSize_jar\ObjectSize.jar</code>
  1. 如何使用该类:
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;"><code>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字节

  • -XX:+UseCompressedClassPointers -XX:+UseCompressedOops 这两个是分开的
  • Oops = ordinary object pointers

Hotspot开启内存压缩的规则(64位机):

  1. 4G以下,直接砍掉高32位
  2. 4G - 32G,默认开启内存压缩ClassPointers Oops (ordinary object pointers)
  3. 32G,压缩无效,使用64位 内存并不是越大越好(^-^)

对象头具体包含什么:

具体看对象的状态

让你吊打面试官的Java内存结构以及对象的内容讲解让你吊打面试官的Java内存结构以及对象的内容讲解

当一个对象计算过identityHashCode之后,不能进入偏向锁状态。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

970

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

606

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

294

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

212

2025.08.29

c++中volatile关键字的作用
c++中volatile关键字的作用

本专题整合了c++中volatile关键字的相关内容,阅读专题下面的文章了解更多详细内容。

75

2025.10.23

class在c语言中的意思
class在c语言中的意思

在C语言中,"class" 是一个关键字,用于定义一个类。想了解更多class的相关内容,可以阅读本专题下面的文章。

809

2024.01.03

python中class的含义
python中class的含义

本专题整合了python中class的相关内容,阅读专题下面的文章了解更多详细内容。

28

2025.12.06

css中的padding属性作用
css中的padding属性作用

在CSS中,padding属性用于设置元素的内边距。想了解更多padding的相关内容,可以阅读本专题下面的文章。

175

2023.12.07

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

23

2026.03.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.2万人学习

C# 教程
C# 教程

共94课时 | 10.9万人学习

Java 教程
Java 教程

共578课时 | 78.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号