前言
本文结合 zero 解释器窥探 字节码 new 的实现逻辑,相关概念可以参考之前的文章
opcode new
参考之前的文章,可以在 bytecodeInterpreter.cpp 文件中找到字节码 new 对应的 case 语句块:
CASE(_new): {
u2 index = Bytes::get_Java_u2(pc+1);
ConstantPool* constants = istate->method()->constants();
if (!constants->tag_at(index).is_unresolved_klass()) {
...
return
}
// Slow case allocation
CALL_VM(InterpreterRuntime::_new(THREAD, METHOD->constants(), index),
handle_exception);
// Must prevent reordering of stores for object initialization
// with stores that publish the new object.
OrderAccess::storestore();
SET_STACK_OBJECT(THREAD->vm_result(), 0);
THREAD->set_vm_result(NULL);
UPDATE_PC_AND_TOS_AND_CONTINUE(3, 1);
}
可以看到大致有两条执行路径
fast case allocation,要创建对象的类已经加载
slow case allocation,要创建对象的类未加载
我们先来看看类未加载的情况
slow case allocation
slow case allocation 会调用 InterpreterRuntime::_new 方法,调用的时候传入了三个参数:
THREAD,线程
METHOD->constants,方法对应的常量池
index,要创建的类在常量池中的索引
常量池是 JVM 里面很重要的一个概念,重要的事情说三遍:ConstantPool! ConstantPool! ConstantPool!
InterpreterRuntime::_new
代码很简洁,似乎没有看到加载 Klass 相关的代码,凭借多年撸代码的经验,加载 Klass 的代码应该是在 pool-> klass_at 函数里面
// interpreterRuntime.cpp
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
接下来的代码分析可能会比较冗长和乏味,如果只想大概了解一下 字节码 new 的实现,到这就够了~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。