Java虚拟机 对象的创建与OOP-Klass模型

在Linux环境下解决JVM崩溃报错:Failed to write core dump. Core dumps have been disabled. To enable core dumping, 一、环境 操作系统:Ubunto 18.04 x64 Java版本:JDK1.8 二、错误信息 出现此错误时,系统会生成名为“hs_err_pidxxxx.log”的日志文件,打开日志文件,会看到类似如下的错误: # # A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0x00007fe8b51c11b1, pid=6840, tid=0x00007fe89f0ce 阅读详情

前言

在前一篇文章中我们学习了Java虚拟机的结构原理与运行时数据区域,那么我们大概知道了Java虚拟机的内存的概况,那么内存中的数据是如何创建和访问的呢?这篇文章会给你答案。

1.对象的创建

对象的创建通常是通过new一个对象而已,当虚拟机接收到一个new指令时,它会做如下的操作。
(1)判断对象对应的类是否加载、链接、初始化
虚拟机接收到一条new指令时,首先会去检查这个指定的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被类加载器加载、链接和初始化过。如果没有则先执行相应的类加载过程。关于类加载器我们在前一篇文章中已经提到过,这里不再赘述。

(2)为对象分配内存
类加载完成后,接着会在Java堆中划分一块内存分配给对象。内存分配根据Java堆是否规整,有两种方式:

  • 指针碰撞:如果Java堆的内存是规整,即所有用过的内存放在一边,而空闲的的放在另一边。分配内存时将位于中间的指针指示器向空闲的内存移动一段与对象大小相等的距离,这样便完成分配内存工作。
  • 空闲列表:如果Java堆的内存不是规整的,则需要由虚拟机维护一个列表来记录那些内存是可用的,这样在分配的时候可以从列表中查询到足够大的内存分配给对象,并在分配后更新列表记录。

Java堆的内存是否规整根据所采用的来及收集器是否带有压缩整理功能有关,关于垃圾收集器,本系列后面的文章会介绍。

(3)处理并发安全问题
创建对象是一个非常频繁的操作,所以需要解决并发的问题,有两种方式:

  • 对分配内存空间的动作进行同步处理,比如在虚拟机采用CAS算法并配上失败重试的方式保证更新操作的原子性。
  • 每个线程在Java堆中预先分配一小块内存,这块内存称为本地线程分配缓冲(Thread Local Allocation Buffer)简写为TLAB,线程需要分配内存时,就在对应线程的TLAB上分配内存,当线程中的TLAB用完并且被分配到了新的TLAB时,这时候才需要同步锁定。通过-XX:+/-UserTLAB参数来设定虚拟机是否使用TLAB。

(4)初始化分配到的内存空间
将分配到的内存,除了对象头都初始化为零值。

(5)设置对象的对象头
将对象的所属类、对象的HashCode和对象的GC分代年龄等数据存储在对象的对象头中。

(6)执行init方法进行初始化
执行init方法,初始化对象的成员变量、调用类的构造方法,这样一个对象就被创建了出来。

2.对象的堆内存布局

对象创建完毕,并且已经在Java堆中分配了内存,那么对象在堆内存是如何进行布局的呢?
以HotSpot虚拟机为例,对象在堆内存的布局分为三个区域,分别是对象头(Header)、实例数据(Instance Data)、对齐填充(Padding)。

  • 对象头:对象头包括两部分信息分别是Mark World和元数据指针,Mark World用于存储对象运行时的数据,比如HashCode、锁状态标志、GC分代年龄等。而元数据指针用于指向方法区的中目标类的类型信息,通过元数据指针可以确定对象的具体类型。
  • 实例数据:用于存储对象中的各种类型的字段信息(包括从父类继承来的)。
  • 对齐填充:对齐填充不一定存在,起到了占位符的作用,没有特别的含义。

对象的内存布局如下图所示。
堆内存布局.png

3.HotSpot的对象模型

HotSpot中采用了OOP-Klass模型,它是用来描述Java对象实例的一种模型,OOP(Ordinary Object Pointer)指的是普通对象指针,而Klass用来描述对象实例的具体类型。
HotSpot中,用instanceOopDesc 和 arrayOopDesc 来描述对象头,其中arrayOopDesc对象用于描述数组类型。
instanceOopDesc的代码如下所示。
openjdk/hotspot/src/share/vm/oops/instanceOop.hpp

     
class instanceOopDesc : public oopDesc {
public:
// aligned header size.
static int header_size() { return sizeof(instanceOopDesc)/HeapWordSize; }
// If compressed, the offset of the fields of the instance may not be aligned.
static int base_offset_in_bytes() {
// offset computation code breaks if UseCompressedClassPointers
// only is true
return (UseCompressedOops && UseCompressedClassPointers) ?
klass_gap_offset_in_bytes() :
sizeof(instanceOopDesc);
}
static bool contains_field_offset(int offset, int nonstatic_field_size) {
int base_in_bytes = base_offset_in_bytes();
return (offset >= base_in_bytes &&
(offset-base_in_bytes) < nonstatic_field_size * heapOopSize);
}
};

可以看出instanceOopDesc继承自oopDesc:
openjdk/hotspot/src/share/vm/oops/oop.hpp

     
class oopDesc {
friend class VMStructs;
private:
volatile markOop _mark;
union _metadata {
Klass* _klass;
narrowKlass _compressed_klass;
} _metadata;
// Fast access to barrier set. Must be initialized.
static BarrierSet* _bs;
...
}

oopDesc中包含两个数据成员:_mark 和 _metadata。其中markOop类型的_mark对象指的是前面讲到的Mark World。_metadata是一个共用体,其中_klass是普通指针,_compressed_klass是压缩类指针,它们就是前面讲到的元数据指针,这两个指针都指向instanceKlass对象,它用来描述对象的具体类型。
instanceKlass的代码如下所示。
openjdk/hotspot/src/share/vm/oops/instanceKlass.hpp

     
class InstanceKlass: public Klass {
...
enum ClassState {
allocated, // allocated (but not yet linked)
loaded, // loaded and inserted in class hierarchy (but not linked yet)
linked, // successfully linked/verified (but not initialized yet)
being_initialized, // currently running class initializer
fully_initialized, // initialized (successfull final state)
initialization_error // error happened during initialization
};
...
}

instanceKlass继承自Klass ,枚举ClassState 用来标识对象的加载进度。
知道了OOP-Klass模型,我们就可以分析Java虚拟机是如何通过栈帧中的对象引用找到对应的对象实例,如下图所示。
OOP-Klass模型(1).png

从图中可以看出,通过栈帧中的对象引用找到Java堆中的instanceOopDesc对象,再通过instanceOopDesc中的元数据指针来找到方法区中的instanceKlass,从而确定该对象的具体类型。

Java虚拟机(二)对象的创建与OOP-Klass模型 在前一篇文章中我们学习了Java虚拟机的结构原理与运行时数据区域,那么我们大概知道了Java虚拟机的内存的概况,那么内存中的数据是如何创建和访问的呢?这篇文章会给你答案。 阅读详情

相关推荐

Hotspot 垃圾回收之CompactibleFreeListSpace(三) 源码解析

目录 1、block_size /block_size_no_stall /block_size_nopar 2、oop_iterate /object_iterate /safe_object_iterate /object_iterate_mem /object_iterate_careful_m 3、save_marks / promote /oop_since_...

菜鸟进阶之路 1258

ARM JDK上CMS一个极小概率发生的bug

这是一个极小概率发生的 bug,因此隐藏的很深。解这个 bug 也耗费了很长时间,虽然最后修复方案就是一行代码,但涉及的知识面还是比较广的。其中 memory barrier 是一个有点绕的概念,GC 算法的细节也需要理解到位。如果读者第一次接触 JVM,希望有耐心看下去,反复推敲,相信你一定会有所收获。

Dreamershi的专栏 1089

5分钟搞懂基因组规模代谢网络(GSMM):从数据库选择到模型构建全流程

本文详细解析基因组规模代谢网络(GSMM)构建的全流程,从数据库选择到模型优化。重点介绍MetaCyc、BiGG等主流数据库的黄金三角评估法则,对比自上而下与自下而上两种建模方法,并提供模型修剪、仿真优化的实用技巧与避坑指南,帮助研究者高效构建精准代谢网络模型。

weixin_30872157的博客 135

(2.1.1.3) JVM内容:对象的生命周期与OOP-Klass模型

目录 一、对象的创建 1.1 判断对象对应的类是否加载、链接、初始化 1.2 为对象分配内存 1.3 处理并发安全问题 1.4 初始化分配到的内存空间 1.5 设置对象的对象头 1.6 执行init方法进行初始化 二、对象的堆内存布局 三、HotSpot的对象模型 3.1 对象、引用与类的关联 四、对象的生命周期 参考文献 一、对象的创建 对象的创建通常是通过new一个...

JAVA成长之路 1134

数据仓库的复用性:设计和构建一个高复用性的数仓

数据仓库的复用性是指在数据仓库的设计和使用过程中,能够实现数据、模型、流程、工具等多个层面的重复利用,减少重复开发,提高开发效率,降低维护成本,并增强灵活性和可扩展性。

z1941563559的博客 1307

schrodinger 薛定谔

链接: https://pan.baidu.com/s/1Duh4GsoytIklvZp7TdHpWg 密码: wmr1 Linux系统版 进入 Schrodinger_Suites_2021-2_Linux-x86_64 sudo ./INSTALL 中间按默认的来即可,也可以自己调整安装目录。安装目录一定要记住。 安装完,把patcher 拷贝到安装目录 sudo ./patcher 点击Patch即可。 启动程序,进入安装目录 ./maestro ...

周迪新的博客 1万+

Java对象分配原理

Java对象模型: OOP-Klass模型 在正式探讨JVM对象的创建前,先简单地介绍一下hotspot中实现的Java的对象模型。在JVM中,并没有直接将Java对象映射成C++对象,而是采用了oop-klass模型,主要是不希望每个对象中都包含有一份虚函数表,其中: OOP(Ordinary Object Point),表示对象的实例信息 Klass,是Java类的在C++中的表示,用来...

sinolover的专栏 990

华为流程L1-L6业务流程深度细化到可执行【附全文阅读】

该文档主要介绍了华为业务流程的深度细化及相关内容,包括流程框架、建模方法、流程模块描述、流程图建模等,旨在帮助企业构建有效的流程体系,实现战略目标。

cdfunlove的博客 4003

java对象模型 指令_Java虚拟机(三):Java对象模型

1 什么是Java对象Java是一门面向对象语言,对象是其最基本的一个组件,在Java程序运行过程中无时无刻不在创建对象、销毁对象,有些对象的生命周期非常短暂(例如在方法内部创建的对象,一般在方法调用之后不长的时间内会被回收销毁),有些对象的生命周期非常漫长(例如HashMap等常驻内存的组件)。那究竟什么是对象?我们先来举个非常简单的例子:自然界中有很多动植物,人类来是动物的一种,人来又可...

weixin_36455339的博客 164

Vue2 - 详细实现安装西瓜视频 xgplayer 插件详细配置及使用教程,利用西瓜视频播放器播放 mp4、flv、hls 格式视频文件及视频推流(直播或监控摄像头画面),支持移动端H5及PC网站!

vue2,nuxt2,西瓜视频,xgplayer,插件组件,xgplayer-hls,xgplayer-flv,xgplayer-mp4,播放视频点播和直播视频流,自定义播放器样式,截屏,监控视频,vue使用西瓜播放器播放flv、hls、mp4视频,截屏按钮,直播流,报错,黑屏,加载失败,苹果ios不兼容,重连,怎么改样式,很卡,详细教程,监控实时播放推流,倍速播放,在线flv在线推流地址,HLS播放,vue西瓜播放器,vue如何使用西瓜视频插件做直播推流回流,视频点播,flv在线视频流播放,截图功能,利用

🏆 前端领域优质创作者 1万+

YOLO26优化:原创自研 | 自研独家创新DSAM注意力 ,基于BiLevelRoutingAttention注意力升级

提出新颖的注意力DSAM(Deformable Bi-level SpatialAttention Module),创新度极佳,适合科研创新,效果秒杀CBAM,Channel Attention+Spartial Attention升级为新颖的Deformable Bi-level Attention+Spartial Attention

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 365

HotSpot 对象的创建

HotSpot中对象是是通过对象模型来表示的,具体来说就是oop和klass来表示,oop代表了一个Java对象在堆内存中的表现形式。使用klass来表示Java类的信息。虚拟机创建Java对象时,会在按照klass所提供的类信息,在内存中创建一个oop对象,具体的内存可能是线程TLAB会堆空间。然后该oop对象的地址会赋给一个变量,这个变量可能在线程栈上或直接来自堆空间对此oop的引用。 一.对象模型 hotspot/src/share/vm/oops/oop.hpp HotSpot内部oop的描述如下,

Sherlock的博客 3122

蓝牙芯片驱动开发-第11章第1题-WiFi蓝牙共存的关键策略有哪些

蓝牙芯片驱动开发-第11章第1题-WiFi蓝牙共存的关键策略有哪些

weixin_42162924的博客 30

深入理解多线程(二)— Java的对象模型

深入理解多线程(二)— Java的对象模型 深入理解多线程(一)—Synchronized的实现原理文章中我们简单介绍过synchronized关键字,通过介绍我们了解到同步代码块使用monitorenter和monitorexit两个指令实现,同步方法使用ACC_SYNCHRONIZED标记符实现。接下来我们将会从JVM源码的角度更加深入的来分析synchronized的具体实现原理。 在进...

渔潭的博客 1163

零基础学simulink仿真建模--基于Simulink进行近端策略优化(PPO)路径规划的仿真建模

特点高效性与稳定性:通过引入剪裁机制,在更新策略时限制步长,从而提高了训练过程的稳定性和效率。适用于多种动作空间:可以处理连续和离散的动作空间问题。无需模型:不需要预先知道环境的确切模型,适合复杂或未知环境。挑战收敛速度与稳定性:确保算法能够在合理的时间内找到近似最优解,并保持训练过程的稳定性。探索与利用平衡:在探索新路径和利用已知信息之间取得平衡。计算资源:对于大规模状态空间和动作空间,计算资源需求较高。首先明确要模拟的任务内容。目标(例如到达指定地点、避开障碍物等)。

amy_mhd的博客 249

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Java虚拟机学习笔记(二)——对象创建、对象内存分布、oop-klass

文章目录对象的创建对象的堆内存分布oop-klass模型 对象的创建 通常情况下,我们是通过new指令完成一个对象的创建的。 虚拟机在接受到一个new指令会做如下操作: 判断对象的类是否加载、链接、初始化 虚拟机在接收到一条new指令时,首先会检查这个指令的参数是否在常量池中定位到一个类的引用,并且检查这个符号引用代表的类是否被类加载器加载、链接和初始化。 为对象分配内存 类加载完成后,接...

PdKingLiu 714

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

JVM成神之路-Java对象模型

首先我们要知道: 在jvm的内存结构中,对象保存在堆中,而我们在对对象进行操作时,其实操作的是对象的引用。 Java对象包含三个部分 一个Java对象可以分为三部分存储在内存中,分别是:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。 对象头(包含锁状态标志,线程持有的锁等标志) 实例数据 对齐填充 oop-klass model(...

Franco的博客 9599

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

java虚拟机(二)

原文:http://liuwangshu.cn/java/jvm/2-oop-kclass.html 1.对象的创建 对象的创建通常是通过new一个对象而已,当虚拟机接收到一个new指令时,它会做如下的操作。 (1)判断对象对应的类是否加载、链接、初始化 虚拟机接收到一条new指令时,首先会去检查这个指定的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类

Dzq_Boyka的博客 386

Java虚拟机核心知识(五) HotSpot的准确式GC

前言 在上一篇文章我们学习到了Java虚拟机是如何利用可达性算法判断对象是否需要回收的,由于在GC进行时,必须暂停所有的Java执行线程(Sun称之为“Stop The World”),所以,虚拟机必须尽量的优化GC过程的效率,减少暂停的时间。那么对于GC Roots,HotSpot是如何快速确定的呢? 对象的创建 首先,我们需要知道在JVM中,对象是如何被创建的。 而对象的创建通常是通过new一...

Natus的博客 2912

探究Jvm源码实现

当我们在Java代码中,使用new创建一个对象实例的时候,(hotspot虚拟机)JVM层面实际上会创建一个instanceOopDesc对象。 Hotspot虚拟机采用OOP-Klass模型来描述Java对象实例,OOP(Ordinary Object Point)指的是普通对象指针,Klass用来描述对象实例的具体类型。Hotspot采用instanceOopDesc和arrayOopDesc来描述对象头,arrayOopDesc对象用来描述数组类型 instanceOopDesc的定义在Hots.

Leon_Jinhai_Sun的博客 204
上一篇: JVM-系统初始化
下一篇: 浏览器中F5和CTRL F5的行为区别
DViewer
博客等级 码龄16年 16粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值