Java对象分配原理

本文介绍了Java对象在JVM中的创建过程,包括OOP-Klass模型、对象创建的入口、初始化klass、内存分配和对象初始化。重点讲解了内存分配中的TLAB(ThreadLocalAllocBuffer)机制以及初始化对象的头部数据设置。
摘要由CSDN通过智能技术生成
本文基于openjdk11及hotspot

Java对象模型: OOP-Klass模型

(想自学习编程的小伙伴请搜索圈T社区,更多行业相关资讯更有行业相关免费视频教程。完全免费哦!)

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

  1. OOP(Ordinary Object Point),表示对象的实例信息
  2. Klass,是Java类的在C++中的表示,用来描述Java类的信息

简单地说,一个Java类在JVM中被拆分为了两个部分:数据和描述信息,分别对应OOP和Klass。

在具体的JVM源码中,当加载一个Class时,会创建一个InstanceKlass对象,实例化的对象则对应InstanceOopDesc,其中InstanceKlass存放在元空间,InstanceOopDesc存放在堆中。

对象创建过程

首先先来看InstanceOopDesc的数据结构,InstanceOopDesc继承了OopDesc,数据结构如下

// 此处为了方便阅读,改写了一下代码
class instanceOopDesc : public oopDesc {
 private:
  volatile markOop _mark;
  union _metadata {
    Klass*      _klass;
    narrowKlass _compressed_klass;
  } _metadata;
};

其中_metadata指向该对象的InstanceKlass,而_mark中则存储了对象运行时的状态数据,数据结构如下(图中为32位的情况下的数据,64位也大同小异)

32 bits:
--------
hash:25 ------------>| age:4    biased_lock:1 lock:2 (normal object)
JavaThread*:23 epoch:2 age:4    biased_lock:1 lock:2 (biased object)
size:32 ------------------------------------------>| (CMS free block)
PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)

每一行都代表了一种情况,描述了哈希码、GC分代年龄、锁等状态信息,如下:

hash: 哈希码
age: 分代年龄
biased_lock: 偏向锁标识位
lock: 锁状态标识位
JavaThread*: 持有偏向锁的线程ID
epoch: 偏向时间戳

instanceOopDesc其实保存的是对象的头部信息,除了头部信息,对象还有数据,对象数据紧跟着头部后面,图示如下:
在这里插入图片描述

1. 入口

在这里插入图片描述
上图截取了一段程序字节码,红线所框对应了Java中new操作的字节码,Java中的new操作对应了字节码的三个操作,本文主要讲述第一个操作(new)。字节码中new操作对应JVM中的InterpreterRuntime::_new,代码如下,

// hotspot/share/interpreter/interpreterRuntime.cpp
IRT_ENTRY(void, InterpreterRuntime::_new(JavaThread* thread, ConstantPool* pool, int index))
  Klass* k = pool->klass_at(index, CHECK);
  InstanceKlass* klass = InstanceKlass::cast(k);

  klass->check_valid_for_instantiation(true, CHECK); // 校验:接口/抽象类/Class不能实例化
  klass->initialize(CHECK); // 初始化klass
  oop obj = klass->allocate_instance(CHECK); // 分配实例

  thread->set_vm_result(obj);
IRT_END

里面主要包含了两个部分:初始化klass和分配实例

2. 初始化klass

// hotspot/share/oops/instanceKlass.cpp
void InstanceKlass::initialize(TRAPS) {
  if (this->should_be_initialized()) {
    initialize_impl(CHECK);
  } else {
    assert(is_initialized(), "sanity check");
  }
}

在这里我们继续看initialize_impl()方法

// hotspot/share/oops/instanceKlass.cpp
void InstanceKlass::initialize_impl(TRAPS) {
  HandleMark hm(THREAD);

  link_class(CHECK);     // 链接class

  bool wait = false;

  // Step 1
  {
    Handle h_init_lock(THREAD, init_lock());
    ObjectLocker ol(h_init_lock, THREAD, h_init_lock() != NULL);

    Thread *self = THREAD;

    // Step 2
    while(i
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值