上文分析了Java类的加载过程,那么Java对象的创建过程是什么样呢?
public class Test {
public static void main(String[] args) {
Test data = new Test();
}
}
以上为例,看下new关键字在底层是怎么实现的。
new关键字实现在InterpreterRuntime类中,如下:
IRT_ENTRY(void, InterpreterRuntime::_new(JavaThread* thread, ConstantPool* pool, int index))
Klass* k_oop = pool->klass_at(index, CHECK);
instanceKlassHandle klass (THREAD, k_oop);
// Make sure we are not instantiating an abstract klass
klass->check_valid_for_instantiation(true, CHECK);
// Make sure klass is initialized
klass->initialize(CHECK);
//分配实例
oop obj = klass->allocate_instance(CHECK);
thread->set_vm_result(obj);
IRT_END
主要分为四步:
- 从常量池pool中获取Klass,如果已加载并符号解析,则直接返回,否则根据情况符号解析或加载并符号解析;
- 检查是否是抽象类
- 初始化
- 分配实例创建对象
第一步的实现方法如下:
Klass* ConstantPool::klass_at_impl(constantPoolHandle this_oop, int which, TRAPS) {
CPSlot entry = this_oop->slot_at(which);
//如果要new的类已经加载并解析过(符号解析),则直接返回
if (entry.is_resolved()) {
assert(entry.get_klass()->is_klass(), "must be");
// Already resolved - return entry.
return entry.get_klass();
}
// 其他略
Symbol* name = NULL;
Handle loader;
{ MonitorLockerEx ml(this_oop->lock());
if (this_oop->tag_at(which).is_unresolved_klass()) {
if (this_oop->tag_at(which).is_unresolved_klass_in_error()) {
in_error = true;
} else {
//从常量池中获取符合引用,类加载器
do_resolve = true;
name = this_oop->unresolved_klass_at(which);
loader = Handle(THREAD, this_oop->pool_holder()->class_loader());
}
}
} // unlocking constantPool
//错误处理略
if (do_resolve) {
// this_oop must be unlocked during resolve_or_fail
oop protection_domain = this_oop->pool_holder()->protdomain();
Handle h_prot (THREAD, protection_domain);
//从SystemDictionary获取已加载的KlassOop,没有加载则加载
Klass* k_oop = SystemDictionary::resolve_or_fail(name, loader, h_prot, true, THREAD);
KlassHandle k;
if (!HAS_PENDING_EXCEPTION) {
k = KlassHandle(THREAD, k_oop);
// preserve the resolved klass.
mirror_handle = Handle(THREAD, k_oop->java_mirror());
// Do access check for klasses
verify_constant_pool_resolve(this_oop, k, THREAD);
}
// 失败处理略
}
if (TraceClassResolution && !k()->oop_is_array()) {
略
} else {
//符合引用变成直接引用,并更新到常量池中
MonitorLockerEx ml(this_oop->lock());
// Only updated constant pool - if it is resolved.
do_resolve = this_oop->tag_at(which).is_unresolved_klass();
if (do_resolve) {
ClassLoaderData* this_key = this_oop->pool_holder()->class_loader_data();
this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM
this_oop->klass_at_put(which, k());
}
}
}
entry = this_oop->resolved_klass_at(which);
assert(entry.is_resolved() && entry.get_klass()->is_klass(), "must be resolved at this point");
return entry.get_klass();
}
第三步初始化是重点:
void InstanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) {
// Make sure klass is linked (verified) before initialization
// A class could already be verified, since it has been reflected upon.
// 如果没有链接(验证、准备、解析)过么,则进行链接
this_oop->link_class(CHECK);
DTRACE_CLASSINIT_PROBE(required, InstanceKlass::cast(this_oop()), -1);
bool wait = false;
// refer to the JVM book page 47 for description of steps
// 以下步骤在《虚拟机规范》中的初始化章节有定义
// Step 1
//获取初始化锁LC(每个类初始化锁唯一),没有则等待
{
oop init_lock = this_oop->init_lock();
ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
Thread *self = THREAD; // it's passed the current thread
// Step 2
// 如果其他线程正在初始化,则释放LC并等待其他线程初始化完成,执行初始化过程不会被中断。
// If we were to use wait() instead of waitInterruptibly() then
// we might end up throwing IE from link/symbol resolution sites
// that aren't expected to throw. This would wreak havoc. See 6320309.
while(this_oop->is_being_initialized() && !this_oop->is_reentrant_initialization(self)) {
wait = true;
ol.waitUninterruptibly(CHECK);
}
// Step 3
// 如果当前线程正在初始化,表明这是对初始化的递归请求(例:A的静态属性创建了B,B的静态属性又创建A),释放LC并返回
if (this_oop->is_being_initialized() && this_oop->is_reentrant_initialization(self)) {
DTRACE_CLASSINIT_PROBE_WAIT(recursive, InstanceKlass::cast(this_oop()), -1,wait);
return;
}
// Step 4
// 如果已经初始化完成,则释放LC并返回
if (this_oop->is_initialized()) {
DTRACE_CLASSINIT_PROBE_WAIT(concurrent, InstanceKlass::cast(this_oop()), -1,wait);
return;
}
// Step 5
//如果初始化发生错误,则抛出NoClassDefFoundError异常
if (this_oop->is_in_error_state()) {
DTRACE_CLASSINIT_PROBE_WAIT(erroneous, InstanceKlass::cast(this_oop()), -1,wait);
ResourceMark rm(THREAD);
const char* desc = "Could not initialize class ";
const char* className = this_oop->external_name();
size_t msglen = strlen(desc) + strlen(className) + 1;
char* message = NEW_RESOURCE_ARRAY(char, msglen);
if (NULL == message) {
// Out of memory: can't create detailed error message
THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), className);
} else {
jio_snprintf(message, msglen, "%s%s", desc, className);
THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), message);
}
}
// Step 6
// 记录下当前线程正在初始化的Class对象
this_oop->set_init_state(being_initialized);
this_oop->set_init_thread(self);
}
// Step 7 如果是类且不是接口,有父类还没有初始化,则触发父类的初始化
Klass* super_klass = this_oop->super();
if (super_klass != NULL && !this_oop->is_interface() && super_klass->should_be_initialized()) {
super_klass->initialize(THREAD);
if (HAS_PENDING_EXCEPTION) {
Handle e(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION;
{
EXCEPTION_MARK;
this_oop->set_initialization_state_and_notify(initialization_error, THREAD); // Locks object, set state, and notify all waiting threads
CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, superclass initialization error is thrown below
}
DTRACE_CLASSINIT_PROBE_WAIT(super__failed, InstanceKlass::cast(this_oop()), -1,wait);
THROW_OOP(e());
}
}
// Recursively initialize any superinterfaces that declare default methods
// Only need to recurse if has_default_methods which includes declaring and
// inheriting default methods
if (this_oop->has_default_methods()) {
this_oop->initialize_super_interfaces(this_oop, CHECK);
}
// Step 8
// 执行初始化方法,即clinit方法
{
assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl");
JavaThread* jt = (JavaThread*)THREAD;
DTRACE_CLASSINIT_PROBE_WAIT(clinit, InstanceKlass::cast(this_oop()), -1,wait);
// Timer includes any side effects of class initialization (resolution,
// etc), but not recursive entry into call_class_initializer().
PerfClassTraceTime timer(ClassLoader::perf_class_init_time(),
ClassLoader::perf_class_init_selftime(),
ClassLoader::perf_classes_inited(),
jt->get_thread_stat()->perf_recursion_counts_addr(),
jt->get_thread_stat()->perf_timers_addr(),
PerfClassTraceTime::CLASS_CLINIT);
this_oop->call_class_initializer(THREAD);
}
// Step 9
// 初始化执行成功,则标记为完全初始化,并通知其他等待的线程,退出。
if (!HAS_PENDING_EXCEPTION) {
this_oop->set_initialization_state_and_notify(fully_initialized, CHECK);
{ ResourceMark rm(THREAD);
debug_only(this_oop->vtable()->verify(tty, true);)
}
}
else {
// Step 10 and 11
// 发生异常且异常不是error或它子类,则构建Exception对象抛出
Handle e(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION;
{
EXCEPTION_MARK;
this_oop->set_initialization_state_and_notify(initialization_error, THREAD);
CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below
}
DTRACE_CLASSINIT_PROBE_WAIT(error, InstanceKlass::cast(this_oop()), -1,wait);
if (e->is_a(SystemDictionary::Error_klass())) {
THROW_OOP(e());
} else {
JavaCallArguments args(e);
THROW_ARG(vmSymbols::java_lang_ExceptionInInitializerError(),
vmSymbols::throwable_void_signature(),
&args);
}
}
DTRACE_CLASSINIT_PROBE_WAIT(end, InstanceKlass::cast(this_oop()), -1,wait);
}
最后创建对象
instanceOop InstanceKlass::allocate_instance(TRAPS) {
bool has_finalizer_flag = has_finalizer(); // Query before possible GC
int size = size_helper(); // Query before forming handle.
KlassHandle h_k(THREAD, this);
instanceOop i;
//创建实例
i = (instanceOop)CollectedHeap::obj_allocate(h_k, size, CHECK_NULL);
if (has_finalizer_flag && !RegisterFinalizersAtInit) {
//注册finalizer
i = register_finalizer(i, CHECK_NULL);
}
return i;
}
继续跟进obj_allocate:
oop CollectedHeap::obj_allocate(KlassHandle klass, int size, TRAPS) {
//略
//分配对象
HeapWord* obj = common_mem_allocate_init(klass, size, CHECK_NULL);
//对象初始化,根据是否使用偏向锁,设置对象头信息等操作。
post_allocation_setup_obj(klass, obj, size);
NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size));
return (oop)obj;
}
继续跟进common_mem_allocate_noinit
···
HeapWord* CollectedHeap::common_mem_allocate_noinit(KlassHandle klass, size_t size, TRAPS) {
// 略
HeapWord* result = NULL;
if (UseTLAB) {
//先尝试快速分配(tlab分配,eden区中线程专属区域),失败则再尝试从tlab中慢速分配,再失败会从eden区共享区域分配
result = allocate_from_tlab(klass, THREAD, size);
if (result != NULL) {
assert(!HAS_PENDING_EXCEPTION,
"Unexpected exception, will result in uninitialized storage");
return result;
}
}
//略
···
从tlab中快速分配失败后(如空间不够),会进入allocate_from_tlab_slow方法:
···
HeapWord* CollectedHeap::allocate_from_tlab_slow(KlassHandle klass, Thread* thread, size_t size) {
// 如果tlab空间大无法discard(这个阈值由TLABRefillWasteFraction比例控制),则记录并返回null(后续会从eden区共享区域分配)
if (thread->tlab().free() > thread->tlab().refill_waste_limit()) {
thread->tlab().record_slow_allocation(size);
return NULL;
}
// 重新分配一个tlab,为了减少内存碎片,此TLAB可能比上一个小
size_t new_tlab_size = thread->tlab().compute_size(size);
thread->tlab().clear_before_allocation();
if (new_tlab_size == 0) {
return NULL;
}
// Allocate a new TLAB...
HeapWord* obj = Universe::heap()->allocate_new_tlab(new_tlab_size);
if (obj == NULL) {
return NULL;
}
//略
return obj;
}
···
实例空间分配完成后,会进行一些初始化操作:
void CollectedHeap::init_obj(HeapWord* obj, size_t size) {
assert(obj != NULL, "cannot initialize NULL object");
const size_t hs = oopDesc::header_size();
assert(size >= hs, "unexpected object size");
//将对象空间除对象头外填0处理
((oop)obj)->set_klass_gap(0);
//先将地址类型转换,然后把堆的字数转化为字节数,再对该段内存进行填值
Copy::fill_to_aligned_words(obj + hs, size - hs);
}
对象的初始化,对象头的填充等操作在post_allocation_setup_obj方法中。