一、解析class文件
hotspot/src/share/vm/classfile/classFileParser.cpp
instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
ClassLoaderData* loader_data,
Handle protection_domain,
KlassHandle host_klass,
GrowableArray<Handle>* cp_patches,
TempNewSymbol& parsed_name,
bool verify,
TRAPS) {
......
// Magic value
// 获取魔数
u4 magic = cfs->get_u4_fast();
......
// Version numbers
// 主次版本号
u2 minor_version = cfs->get_u2_fast();
u2 major_version = cfs->get_u2_fast();
......
// Constant pool
// 解析常量池
constantPoolHandle cp = parse_constant_pool(CHECK_(nullHandle));
......
// Access flags
// 权限标识
AccessFlags access_flags;
jint flags = cfs->get_u2_fast() & JVM_RECOGNIZED_CLASS_MODIFIERS;
if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION) {
// Set abstract bit for old class files for backward compatibility
flags |= JVM_ACC_ABSTRACT;
}
verify_legal_class_modifiers(flags, CHECK_(nullHandle));
access_flags.set_flags(flags);
// This class and superclass
// 当前类和父类
u2 this_class_index = cfs->get_u2_fast();
check_property(
valid_cp_range(this_class_index, cp_size) &&
cp->tag_at(this_class_index).is_unresolved_klass(),
"Invalid this class index %u in constant pool in class file %s",
this_class_index, CHECK_(nullHandle));
// 从常量池中获取类信息
Symbol* class_name = cp->unresolved_klass_at(this_class_index);
assert(class_name != NULL, "class_name can't be null");
......
// 父类索引
u2 super_class_index = cfs->get_u2_fast();
// 解析父类
instanceKlassHandle super_klass = parse_super_class(super_class_index,
CHECK_NULL);
// Interfaces
// 接口
u2 itfs_len = cfs->get_u2_fast();
// 解析接口
Array<Klass*>* local_interfaces =
parse_interfaces(itfs_len, protection_domain, _class_name,
&has_default_methods, CHECK_(nullHandle));
u2 java_fields_count = 0;
// Fields (offsets are filled in later)
FieldAllocationCount fac;
// 解析字段
Array<u2>* fields = parse_fields(class_name,
access_flags.is_interface(),
&fac, &java_fields_count,
CHECK_(nullHandle));
// Methods
bool has_final_method = false;
AccessFlags promoted_flags;
promoted_flags.set_flags(0);
// 解析方法
Array<Method*>* methods = parse_methods(access_flags.is_interface(),
&promoted_flags,
&has_final_method,
&declares_default_methods,
CHECK_(nullHandle));
......
int vtable_size = 0;
int itable_size = 0;
int num_miranda_methods = 0;
GrowableArray<Method*> all_mirandas(20);
// 统计虚函数表个数
klassVtable::compute_vtable_size_and_num_mirandas(
&vtable_size, &num_miranda_methods, &all_mirandas, super_klass(), methods,
access_flags, class_loader, class_name, local_interfaces,
CHECK_(nullHandle));
// Size of Java itable (in words)
// 统计接口函数表个数
itable_size = access_flags.is_interface() ? 0 : klassItable::compute_itable_size(_transitive_interfaces);
......
// We can now create the basic Klass* for this klass
// 创建InstanceKlass对象,保存class文件解析的结果
_klass = InstanceKlass::allocate_instance_klass(loader_data,
vtable_size,
itable_size,
info.static_field_size,
total_oop_map_size2,
rt,
access_flags,
name,
super_klass(),
!host_klass.is_null(),
CHECK_(nullHandle));
instanceKlassHandle this_klass (THREAD, _klass);
......
}
1. 解析常量池
constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
ClassFileStream* cfs = stream();
constantPoolHandle nullHandle;
cfs->guarantee_more(3, CHECK_(nullHandle)); // length, first cp tag
// 常量池大小
u2 length = cfs->get_u2_fast();
guarantee_property(
length >= 1, "Illegal constant pool size %u in class file %s",
length, CHECK_(nullHandle));
// 在元空间给常量池分配内存
ConstantPool* constant_pool = ConstantPool::allocate(_loader_data, length,
CHECK_(nullHandle));
_cp = constant_pool; // save in case of errors
constantPoolHandle cp (THREAD, constant_pool);
// parsing constant pool entries
// 解析常量池数据存储到ConstantPool中
parse_constant_pool_entries(length, CHECK_(nullHandle));
int index = 1; // declared outside of loops for portability
......
}
void ClassFileParser::parse_constant_pool_entries(int length, TRAPS) {
// Use a local copy of ClassFileStream. It helps the C++ compiler to optimize
// this function (_current can be allocated in a register, with scalar
// replacement of aggregates). The _current pointer is copied back to
// stream() when this function returns. DON'T call another method within
// this method that uses stream().
ClassFileStream* cfs0 = stream();
ClassFileStream cfs1 = *cfs0;
ClassFileStream* cfs = &cfs1;
#ifdef ASSERT
assert(cfs->allocated_on_stack(),"should be local");
u1* old_current = cfs0->current();
#endif
Handle class_loader(THREAD, _loader_data->class_loader());
// Used for batching symbol allocations.
const char* names[SymbolTable::symbol_alloc_batch_size];
int lengths[SymbolTable::symbol_alloc_batch_size];
int indices[SymbolTable::symbol_alloc_batch_size];
unsigned int hashValues[SymbolTable::symbol_alloc_batch_size];
int names_count = 0;
// parsing Index 0 is unused
for (int index = 1; index < length; index++) {
// Each of the following case guarantees one more byte in the stream
// for the following tag or the access_flags following constant pool,
// so we don't need bounds-check for reading tag.
u1 tag = cfs->get_u1_fast();
switch (tag) {
// 类信息
case JVM_CONSTANT_Class :
{
cfs->guarantee_more(3, CHECK); // name_index, tag/access_flags
// 类名索引
u2 name_index = cfs->get_u2_fast();
// 暂存在常量池对象模型当中
_cp->klass_index_at_put(index, name_index);
}
break;
// 字段
case JVM_CONSTANT_Fieldref :
{
cfs->guarantee_more(5, CHECK); // class_index, name_and_type_index, tag/access_flags
// 所属类索引
u2 class_index = cfs->get_u2_fast();
// 字段信息索引
u2 name_and_type_index = cfs->get_u2_fast();
_cp->field_at_put(index, class_index, name_and_type_index);
}
break;
// 方法
case JVM_CONSTANT_Methodref :
{
cfs->guarantee_more(5, CHECK); // class_index, name_and_type_index, tag/access_flags
u2 class_index = cfs->get_u2_fast();
u2 name_and_type_index = cfs->get_u2_fast();
_cp->method_at_put(index, class_index, name_and_type_index);
}
break;
case JVM_CONSTANT_InterfaceMethodref :
{
cfs->guarantee_more(5, CHECK); // class_index, name_and_type_index, tag/access_flags
// 所属类索引
u2 class_index = cfs->get_u2_fast();
// 方法信息索引
u2 name_and_type_index = cfs->get_u2_fast();
_cp->interface_method_at_put(index, class_index, name_and_type_index);
}
break;
// 字符串信息
case JVM_CONSTANT_String :
{
cfs->guarantee_more(3, CHECK); // string_index, tag/access_flags
// 字符串索引
u2 string_index = cfs->get_u2_fast();
_cp->string_index_at_put(index, string_index);
}
break;
// 方法句柄类型决定字节码行为
case JVM_CONSTANT_MethodHandle :
case JVM_CONSTANT_MethodType :
if (_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
classfile_parse_error(
"Class file version does not support constant tag %u in class file %s",
tag, CHECK);
}
if (!EnableInvokeDynamic) {
classfile_parse_error(
"This JVM does not support constant tag %u in class file %s",
tag, CHECK);
}
if (tag == JVM_CONSTANT_MethodHandle) {
cfs->guarantee_more(4, CHECK); // ref_kind, method_index, tag/access_flags
u1 ref_kind = cfs->get_u1_fast();
u2 method_index = cfs->get_u2_fast();
_cp->method_handle_index_at_put(index, ref_kind, method_index);
} else if (tag == JVM_CONSTANT_MethodType) {
cfs->guarantee_more(3, CHECK); // signature_index, tag/access_flags
u2 signature_index = cfs->get_u2_fast();
_cp->method_type_index_at_put(index, signature_index);
} else {
ShouldNotReachHere();
}
break;
// 动态调用
case JVM_CONSTANT_InvokeDynamic :
{
if (_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
classfile_parse_error(
"Class file version does not support constant tag %u in class file %s",
tag, CHECK);
}
if (!EnableInvokeDynamic) {
classfile_parse_error(
"This JVM does not support constant tag %u in class file %s",
tag, CHECK);
}
cfs->guarantee_more(5, CHECK); // bsm_index, nt, tag/access_flags
u2 bootstrap_specifier_index = cfs->get_u2_fast();
u2 name_and_type_index = cfs->get_u2_fast();
if (_max_bootstrap_specifier_index < (int) bootstrap_specifier_index)
_max_bootstrap_specifier_index = (int) bootstrap_specifier_index; // collect for later
_cp->invoke_dynamic_at_put(index, bootstrap_specifier_index, name_and_type_index);
}
break;
case JVM_CONSTANT_Integer :
{
cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags
u4 bytes = cfs->get_u4_fast();
_cp->int_at_put(index, (jint) bytes);
}
break;
case JVM_CONSTANT_Float :
{
cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags
u4 bytes = cfs->get_u4_fast();
_cp->float_at_put(index, *(jfloat*)&bytes);
}
break;
case JVM_CONSTANT_Long :
// A mangled type might cause you to overrun allocated memory
guarantee_property(index+1 < length,
"Invalid constant pool entry %u in class file %s",
index, CHECK);
{
cfs->guarantee_more(9, CHECK); // bytes, tag/access_flags
u8 bytes = cfs->get_u8_fast();
_cp->long_at_put(index, bytes);
}
index++; // Skip entry following eigth-byte constant, see JVM book p. 98
break;
case JVM_CONSTANT_Double :
// A mangled type might cause you to overrun allocated memory
guarantee_property(index+1 < length,
"Invalid constant pool entry %u in class file %s",
index, CHECK);
{
cfs->guarantee_more(9, CHECK); // bytes, tag/access_flags
u8 bytes = cfs->get_u8_fast();
_cp->double_at_put(index, *(jdouble*)&bytes);
}
index++; // Skip entry following eigth-byte constant, see JVM book p. 98
break;
case JVM_CONSTANT_NameAndType :
{
cfs->guarantee_more(5, CHECK); // name_index, signature_index, tag/access_flags
u2 name_index = cfs->get_u2_fast();
u2 signature_index = cfs->get_u2_fast();
_cp->name_and_type_at_put(index, name_index, signature_index);
}
break;
// 编码码点
case JVM_CONSTANT_Utf8 :
{
cfs->guarantee_more(2, CHECK); // utf8_length
u2 utf8_length = cfs->get_u2_fast();
u1* utf8_buffer = cfs->get_u1_buffer();
assert(utf8_buffer != NULL, "null utf8 buffer");
// Got utf8 string, guarantee utf8_length+1 bytes, set stream position forward.
cfs->guarantee_more(utf8_length+1, CHECK); // utf8 string, tag/access_flags
cfs->skip_u1_fast(utf8_length);
// Before storing the symbol, make sure it's legal
if (_need_verify) {
verify_legal_utf8((unsigned char*)utf8_buffer, utf8_length, CHECK);
}
if (EnableInvokeDynamic && has_cp_patch_at(index)) {
Handle patch = clear_cp_patch_at(index);
guarantee_property(java_lang_String::is_instance(patch()),
"Illegal utf8 patch at %d in class file %s",
index, CHECK);
char* str = java_lang_String::as_utf8_string(patch());
// (could use java_lang_String::as_symbol instead, but might as well batch them)
utf8_buffer = (u1*) str;
utf8_length = (int) strlen(str);
}
unsigned int hash;
Symbol* result = SymbolTable::lookup_only((char*)utf8_buffer, utf8_length, hash);
if (result == NULL) {
names[names_count] = (char*)utf8_buffer;
lengths[names_count] = utf8_length;
indices[names_count] = index;
hashValues[names_count++] = hash;
if (names_count == SymbolTable::symbol_alloc_batch_size) {
SymbolTable::new_symbols(_loader_data, _cp, names_count, names, lengths, indices, hashValues, CHECK);
names_count = 0;
}
} else {
_cp->symbol_at_put(index, result);
}
}
break;
default:
classfile_parse_error(
"Unknown constant tag %u in class file %s", tag, CHECK);
break;
}
}
// Allocate the remaining symbols
// 分配符号表
if (names_count > 0) {
SymbolTable::new_symbols(_loader_data, _cp, names_count, names, lengths, indices, hashValues, CHECK);
}
// Copy _current pointer of local copy back to stream().
#ifdef ASSERT
assert(cfs0->current() == old_current, "non-exclusive use of stream()");
#endif
cfs0->set_current(cfs1.current());
}
2.解析接口
Array<Klass*>* ClassFileParser::parse_interfaces(int length,
Handle protection_domain,
Symbol* class_name,
bool* has_default_methods,
TRAPS) {
if (length == 0) {
_local_interfaces = Universe::the_empty_klass_array();
} else {
ClassFileStream* cfs = stream();
assert(length > 0, "only called for length>0");
_local_interfaces = MetadataFactory::new_array<Klass*>(_loader_data, length, NULL, CHECK_NULL);
int index;
for (index = 0; index < length; index++) {
u2 interface_index = cfs->get_u2(CHECK_NULL);
KlassHandle interf;
check_property(
valid_klass_reference_at(interface_index),
"Interface name has bad constant pool index %u in class file %s",
interface_index, CHECK_NULL);
if (_cp->tag_at(interface_index).is_klass()) {
interf = KlassHandle(THREAD, _cp->resolved_klass_at(interface_index));
} else {
Symbol* unresolved_klass = _cp->klass_name_at(interface_index);
// Don't need to check legal name because it's checked when parsing constant pool.
// But need to make sure it's not an array type.
guarantee_property(unresolved_klass->byte_at(0) != JVM_SIGNATURE_ARRAY,
"Bad interface name in class file %s", CHECK_NULL);
Handle class_loader(THREAD, _loader_data->class_loader());
// Call resolve_super so classcircularity is checked
Klass* k = SystemDictionary::resolve_super_or_fail(class_name,
unresolved_klass, class_loader, protection_domain,
false, CHECK_NULL);
interf = KlassHandle(THREAD, k);
}
if (!interf()->is_interface()) {
THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), "Implementing class", NULL);
}
if (InstanceKlass::cast(interf())->has_default_methods()) {
*has_default_methods = true;
}
_local_interfaces->at_put(index, interf());
}
if (!_need_verify || length <= 1) {
return _local_interfaces;
}
// Check if there's any duplicates in interfaces
ResourceMark rm(THREAD);
NameSigHash** interface_names = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, NameSigHash*, HASH_ROW_SIZE);
initialize_hashtable(interface_names);
bool dup = false;
{
debug_only(No_Safepoint_Verifier nsv;)
for (index = 0; index < length; index++) {
Klass* k = _local_interfaces->at(index);
Symbol* name = InstanceKlass::cast(k)->name();
// If no duplicates, add (name, NULL) in hashtable interface_names.
if (!put_after_lookup(name, NULL, interface_names)) {
dup = true;
break;
}
}
}
if (dup) {
classfile_parse_error("Duplicate interface name in class file %s", CHECK_NULL);
}
}
return _local_interfaces;
}
3. 类字段解析
Array<u2>* ClassFileParser::parse_fields(Symbol* class_name,
bool is_interface,
FieldAllocationCount *fac,
u2* java_fields_count_ptr, TRAPS) {
ClassFileStream* cfs = stream();
cfs->guarantee_more(2, CHECK_NULL); // length
u2 length = cfs->get_u2_fast();
*java_fields_count_ptr = length;
int num_injected = 0;
InjectedField* injected = JavaClasses::get_injected(class_name, &num_injected);
int total_fields = length + num_injected;
// The field array starts with tuples of shorts
// [access, name index, sig index, initial value index, byte offset].
// A generic signature slot only exists for field with generic
// signature attribute. And the access flag is set with
// JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE for that field. The generic
// signature slots are at the end of the field array and after all
// other fields data.
//
// f1: [access, name index, sig index, initial value index, low_offset, high_offset]
// f2: [access, name index, sig index, initial value index, low_offset, high_offset]
// ...
// fn: [access, name index, sig index, initial value index, low_offset, high_offset]
// [generic signature index]
// [generic signature index]
// ...
//
// Allocate a temporary resource array for field data. For each field,
// a slot is reserved in the temporary array for the generic signature
// index. After parsing all fields, the data are copied to a permanent
// array and any unused slots will be discarded.
ResourceMark rm(THREAD);
u2* fa = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2, total_fields * (FieldInfo::field_slots + 1));
// The generic signature slots start after all other fields' data.
int generic_signature_slot = total_fields * FieldInfo::field_slots;
int num_generic_signature = 0;
for (int n = 0; n < length; n++) {
cfs->guarantee_more(8, CHECK_NULL); // access_flags, name_index, descriptor_index, attributes_count
AccessFlags access_flags;
jint flags = cfs->get_u2_fast() & JVM_RECOGNIZED_FIELD_MODIFIERS;
verify_legal_field_modifiers(flags, is_interface, CHECK_NULL);
access_flags.set_flags(flags);
//字段类型索引
u2 name_index = cfs->get_u2_fast();
int cp_size = _cp->length();
check_property(valid_symbol_at(name_index),
"Invalid constant pool index %u for field name in class file %s",
name_index,
CHECK_NULL);
Symbol* name = _cp->symbol_at(name_index);
verify_legal_field_name(name, CHECK_NULL);
//字段名索引
u2 signature_index = cfs->get_u2_fast();
check_property(valid_symbol_at(signature_index),
"Invalid constant pool index %u for field signature in class file %s",
signature_index, CHECK_NULL);
Symbol* sig = _cp->symbol_at(signature_index);
verify_legal_field_signature(name, sig, CHECK_NULL);
//字段信息
u2 constantvalue_index = 0;
bool is_synthetic = false;
u2 generic_signature_index = 0;
bool is_static = access_flags.is_static();
FieldAnnotationCollector parsed_annotations(_loader_data);
//属性解析
u2 attributes_count = cfs->get_u2_fast();
if (attributes_count > 0) {
parse_field_attributes(attributes_count, is_static, signature_index,
&constantvalue_index, &is_synthetic,
&generic_signature_index, &parsed_annotations,
CHECK_NULL);
if (parsed_annotations.field_annotations() != NULL) {
if (_fields_annotations == NULL) {
_fields_annotations = MetadataFactory::new_array<AnnotationArray*>(
_loader_data, length, NULL,
CHECK_NULL);
}
_fields_annotations->at_put(n, parsed_annotations.field_annotations());
parsed_annotations.set_field_annotations(NULL);
}
if (parsed_annotations.field_type_annotations() != NULL) {
if (_fields_type_annotations == NULL) {
_fields_type_annotations = MetadataFactory::new_array<AnnotationArray*>(
_loader_data, length, NULL,
CHECK_NULL);
}
_fields_type_annotations->at_put(n, parsed_annotations.field_type_annotations());
parsed_annotations.set_field_type_annotations(NULL);
}
if (is_synthetic) {
access_flags.set_is_synthetic();
}
if (generic_signature_index != 0) {
access_flags.set_field_has_generic_signature();
fa[generic_signature_slot] = generic_signature_index;
generic_signature_slot ++;
num_generic_signature ++;
}
}
//字段初始化
FieldInfo* field = FieldInfo::from_field_array(fa, n);
field->initialize(access_flags.as_short(),
name_index,
signature_index,
constantvalue_index);
BasicType type = _cp->basic_type_for_signature_at(signature_index);
// Remember how many oops we encountered and compute allocation type
FieldAllocationType atype = fac->update(is_static, type);
field->set_allocation_type(atype);
// After field is initialized with type, we can augment it with aux info
if (parsed_annotations.has_any_annotations())
parsed_annotations.apply_to(field);
}
int index = length;
if (num_injected != 0) {
for (int n = 0; n < num_injected; n++) {
// Check for duplicates
if (injected[n].may_be_java) {
Symbol* name = injected[n].name();
Symbol* signature = injected[n].signature();
bool duplicate = false;
for (int i = 0; i < length; i++) {
FieldInfo* f = FieldInfo::from_field_array(fa, i);
if (name == _cp->symbol_at(f->name_index()) &&
signature == _cp->symbol_at(f->signature_index())) {
// Symbol is desclared in Java so skip this one
duplicate = true;
break;
}
}
if (duplicate) {
// These will be removed from the field array at the end
continue;
}
}
// Injected field
FieldInfo* field = FieldInfo::from_field_array(fa, index);
field->initialize(JVM_ACC_FIELD_INTERNAL,
injected[n].name_index,
injected[n].signature_index,
0);
BasicType type = FieldType::basic_type(injected[n].signature());
// Remember how many oops we encountered and compute allocation type
FieldAllocationType atype = fac->update(false, type);
field->set_allocation_type(atype);
index++;
}
}
// Now copy the fields' data from the temporary resource array.
// Sometimes injected fields already exist in the Java source so
// the fields array could be too long. In that case the
// fields array is trimed. Also unused slots that were reserved
// for generic signature indexes are discarded.
Array<u2>* fields = MetadataFactory::new_array<u2>(
_loader_data, index * FieldInfo::field_slots + num_generic_signature,
CHECK_NULL);
_fields = fields; // save in case of error
{
int i = 0;
for (; i < index * FieldInfo::field_slots; i++) {
fields->at_put(i, fa[i]);
}
for (int j = total_fields * FieldInfo::field_slots;
j < generic_signature_slot; j++) {
fields->at_put(i++, fa[j]);
}
assert(i == fields->length(), "");
}
if (_need_verify && length > 1) {
// Check duplicated fields
ResourceMark rm(THREAD);
NameSigHash** names_and_sigs = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, NameSigHash*, HASH_ROW_SIZE);
initialize_hashtable(names_and_sigs);
bool dup = false;
{
debug_only(No_Safepoint_Verifier nsv;)
for (AllFieldStream fs(fields, _cp); !fs.done(); fs.next()) {
Symbol* name = fs.name();
Symbol* sig = fs.signature();
// If no duplicates, add name/signature in hashtable names_and_sigs.
if (!put_after_lookup(name, sig, names_and_sigs)) {
dup = true;
break;
}
}
}
if (dup) {
classfile_parse_error("Duplicate field name&signature in class file %s",
CHECK_NULL);
}
}
return fields;
}
4.方法解析
Array<Method*>* ClassFileParser::parse_methods(bool is_interface,
AccessFlags* promoted_flags,
bool* has_final_method,
bool* declares_default_methods,
TRAPS) {
ClassFileStream* cfs = stream();
cfs->guarantee_more(2, CHECK_NULL); // length
u2 length = cfs->get_u2_fast();
if (length == 0) {
_methods = Universe::the_empty_method_array();
} else {
_methods = MetadataFactory::new_array<Method*>(_loader_data, length, NULL, CHECK_NULL);
HandleMark hm(THREAD);
for (int index = 0; index < length; index++) {
// 解析方法
methodHandle method = parse_method(is_interface,
promoted_flags,
CHECK_NULL);
.......
}
......
}
methodHandle ClassFileParser::parse_method(bool is_interface,
AccessFlags *promoted_flags,
TRAPS) {
.......// 省略一大堆解析
// 在元空间创建Method模型
Method* m = Method::allocate(
_loader_data, code_length, access_flags, &sizes,
ConstMethod::NORMAL, CHECK_(nullHandle));
ClassLoadingService::add_class_method_size(m->size()*HeapWordSize);
// Fill in information from fixed part (access_flags already set)
// 向模型中填充方法信息
m->set_constants(_cp);
m->set_name_index(name_index);
m->set_signature_index(signature_index);
#ifdef CC_INTERP
// hmm is there a gc issue here??
ResultTypeFinder rtf(_cp->symbol_at(signature_index));
m->set_result_index(rtf.type());
#endif
if (args_size >= 0) {
m->set_size_of_parameters(args_size);
} else {
m->compute_size_of_parameters(THREAD);
}
#ifdef ASSERT
if (args_size >= 0) {
m->compute_size_of_parameters(THREAD);
assert(args_size == m->size_of_parameters(), "");
}
#endif
// Fill in code attribute information
// 填充代码属性信息
m->set_max_stack(max_stack);
m->set_max_locals(max_locals);
if (stackmap_data != NULL) {
m->constMethod()->copy_stackmap_data(_loader_data, stackmap_data,
stackmap_data_length, CHECK_NULL);
}
// Copy byte codes
// 复制方法中的code指令
m->set_code(code_start);
// Copy line number table
if (linenumber_table != NULL) {
memcpy(m->compressed_linenumber_table(),
linenumber_table->buffer(), linenumber_table_length);
}
// Copy exception table
if (exception_table_length > 0) {
int size =
exception_table_length * sizeof(ExceptionTableElement) / sizeof(u2);
copy_u2_with_conversion((u2*) m->exception_table_start(),
exception_table_start, size);
}
// Copy method parameters
//行号表
//异常表
//方法参数
if (method_parameters_length > 0) {
MethodParametersElement* elem = m->constMethod()->method_parameters_start();
for (int i = 0; i < method_parameters_length; i++) {
elem[i].name_cp_index = Bytes::get_Java_u2(method_parameters_data);
method_parameters_data += 2;
elem[i].flags = Bytes::get_Java_u2(method_parameters_data);
method_parameters_data += 2;
}
}
// Copy checked exceptions
if (checked_exceptions_length > 0) {
int size = checked_exceptions_length * sizeof(CheckedExceptionElement) / sizeof(u2);
copy_u2_with_conversion((u2*) m->checked_exceptions_start(), checked_exceptions_start, size);
}
// Copy class file LVT's/LVTT's into the HotSpot internal LVT.
//类本地变量
if (total_lvt_length > 0) {
promoted_flags->set_has_localvariable_table();
copy_localvariable_table(m->constMethod(), lvt_cnt,
localvariable_table_length,
localvariable_table_start,
lvtt_cnt,
localvariable_type_table_length,
localvariable_type_table_start, CHECK_NULL);
}
if (parsed_annotations.has_any_annotations())
parsed_annotations.apply_to(m);
// Copy annotations
//拷贝注解信息
copy_method_annotations(m->constMethod(),
runtime_visible_annotations,
runtime_visible_annotations_length,
runtime_invisible_annotations,
runtime_invisible_annotations_length,
runtime_visible_parameter_annotations,
runtime_visible_parameter_annotations_length,
runtime_invisible_parameter_annotations,
runtime_invisible_parameter_annotations_length,
runtime_visible_type_annotations,
runtime_visible_type_annotations_length,
runtime_invisible_type_annotations,
runtime_invisible_type_annotations_length,
annotation_default,
annotation_default_length,
CHECK_NULL);
if (name == vmSymbols::finalize_method_name() &&
signature == vmSymbols::void_method_signature()) {
if (m->is_empty_method()) {
_has_empty_finalizer = true;
} else {
_has_finalizer = true;
}
}
if (name == vmSymbols::object_initializer_name() &&
signature == vmSymbols::void_method_signature() &&
m->is_vanilla_constructor()) {
_has_vanilla_constructor = true;
}
NOT_PRODUCT(m->verify());
return m;
}
5.创建InstanceKlass
hotspot/src/share/vm/oops/instanceKlass.cpp
InstanceKlass* InstanceKlass::allocate_instance_klass(
ClassLoaderData* loader_data,
int vtable_len,
int itable_len,
int static_field_size,
int nonstatic_oop_map_size,
ReferenceType rt,
AccessFlags access_flags,
Symbol* name,
Klass* super_klass,
bool is_anonymous,
TRAPS) {
int size = InstanceKlass::size(vtable_len, itable_len, nonstatic_oop_map_size,
access_flags.is_interface(), is_anonymous);
// Allocation
InstanceKlass* ik;
if (rt == REF_NONE) {
if (name == vmSymbols::java_lang_Class()) {
ik = new (loader_data, size, THREAD) InstanceMirrorKlass(
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
access_flags, is_anonymous);
} else if (name == vmSymbols::java_lang_ClassLoader() ||
(SystemDictionary::ClassLoader_klass_loaded() &&
super_klass != NULL &&
super_klass->is_subtype_of(SystemDictionary::ClassLoader_klass()))) {
ik = new (loader_data, size, THREAD) InstanceClassLoaderKlass(
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
access_flags, is_anonymous);
} else {
// normal class
ik = new (loader_data, size, THREAD) InstanceKlass(
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
access_flags, is_anonymous);
}
} else {
// reference klass
ik = new (loader_data, size, THREAD) InstanceRefKlass(
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
access_flags, is_anonymous);
}
// Check for pending exception before adding to the loader data and incrementing
// class count. Can get OOM here.
if (HAS_PENDING_EXCEPTION) {
return NULL;
}
// Add all classes to our internal class loader list here,
// including classes in the bootstrap (NULL) class loader.
//关联kclass到类加载器
loader_data->add_class(ik);
Atomic::inc(&_total_instanceKlass_count);
return ik;
}
hotspot/src/share/vm/oops/klass.cpp
void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw() {
return Metaspace::allocate(loader_data, word_size, /*read_only*/false,
MetaspaceObj::ClassType, CHECK_NULL);
}
hotspot/src/share/vm/memory/metaspace.cpp
MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
bool read_only, MetaspaceObj::Type type, TRAPS) {
if (HAS_PENDING_EXCEPTION) {
assert(false, "Should not allocate with exception pending");
return NULL; // caller does a CHECK_NULL too
}
assert(loader_data != NULL, "Should never pass around a NULL loader_data. "
"ClassLoaderData::the_null_class_loader_data() should have been used.");
// Allocate in metaspaces without taking out a lock, because it deadlocks
// with the SymbolTable_lock. Dumping is single threaded for now. We'll have
// to revisit this for application class data sharing.
if (DumpSharedSpaces) {
assert(type > MetaspaceObj::UnknownType && type < MetaspaceObj::_number_of_types, "sanity");
Metaspace* space = read_only ? loader_data->ro_metaspace() : loader_data->rw_metaspace();
MetaWord* result = space->allocate(word_size, NonClassType);
if (result == NULL) {
report_out_of_shared_space(read_only ? SharedReadOnly : SharedReadWrite);
}
if (PrintSharedSpaces) {
space->record_allocation(result, type, space->vsm()->get_raw_word_size(word_size));
}
// Zero initialize.
Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0);
return result;
}
MetadataType mdtype = (type == MetaspaceObj::ClassType) ? ClassType : NonClassType;
// Try to allocate metadata.
MetaWord* result = loader_data->metaspace_non_null()->allocate(word_size, mdtype);
if (result == NULL) {
tracer()->report_metaspace_allocation_failure(loader_data, word_size, type, mdtype);
// Allocation failed.
if (is_init_completed()) {
// Only start a GC if the bootstrapping has completed.
// Try to clean out some memory and retry.
result = Universe::heap()->collector_policy()->satisfy_failed_metadata_allocation(
loader_data, word_size, mdtype);
}
}
if (result == NULL) {
report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL);
}
// Zero initialize.
Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0);
return result;
}
二、链接
hotspot/src/share/vm/classfile/systemDictionary.cpp
instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
......
// 加载class文件
if (k.is_null()) {
// Use VM class loader
PerfTraceTime vmtimer(ClassLoader::perf_sys_classload_time());
k = ClassLoader::load_classfile(class_name, CHECK_(nh));
}
// find_or_define_instance_class may return a different InstanceKlass
// 定义类
if (!k.is_null()) {
k = find_or_define_instance_class(class_name, class_loader, k, CHECK_(nh));
}
......
}
instanceKlassHandle SystemDictionary::find_or_define_instance_class(Symbol* class_name, Handle class_loader, instanceKlassHandle k, TRAPS) {
......
define_instance_class(k, THREAD);
......
}
void SystemDictionary::define_instance_class(instanceKlassHandle k, TRAPS) {
......
k->eager_initialize(THREAD);
......
}
hotspot/src/share/vm/oops/instanceKlass.cpp
void InstanceKlass::eager_initialize(Thread *thread) {
......
eager_initialize_impl(this_oop);
......
}
void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_oop) {
......
link_class_impl(this_oop, true, THREAD);
......
}
hotspot/src/share/vm/oops/instanceKlass.cpp
bool InstanceKlass::link_class_impl(
instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS) {
// check for error state
if (this_oop->is_in_error_state()) {
ResourceMark rm(THREAD);
THROW_MSG_(vmSymbols::java_lang_NoClassDefFoundError(),
this_oop->external_name(), false);
}
// return if already verified
// 如果已链接,直接返回
if (this_oop->is_linked()) {
return true;
}
// Timing
// timer handles recursion
assert(THREAD->is_Java_thread(), "non-JavaThread in link_class_impl");
JavaThread* jt = (JavaThread*)THREAD;
// link super class before linking this class
// 对父类进行链接
instanceKlassHandle super(THREAD, this_oop->super());
if (super.not_null()) {
if (super->is_interface()) { // check if super class is an interface
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IncompatibleClassChangeError(),
"class %s has interface %s as super class",
this_oop->external_name(),
super->external_name()
);
return false;
}
link_class_impl(super, throw_verifyerror, CHECK_false);
}
// link all interfaces implemented by this class before linking this class
// 链接接口
Array<Klass*>* interfaces = this_oop->local_interfaces();
int num_interfaces = interfaces->length();
for (int index = 0; index < num_interfaces; index++) {
HandleMark hm(THREAD);
instanceKlassHandle ih(THREAD, interfaces->at(index));
link_class_impl(ih, throw_verifyerror, CHECK_false);
}
// in case the class is linked in the process of linking its superclasses
if (this_oop->is_linked()) {
return true;
}
// trace only the link time for this klass that includes
// the verification time
PerfClassTraceTime vmtimer(ClassLoader::perf_class_link_time(),
ClassLoader::perf_class_link_selftime(),
ClassLoader::perf_classes_linked(),
jt->get_thread_stat()->perf_recursion_counts_addr(),
jt->get_thread_stat()->perf_timers_addr(),
PerfClassTraceTime::CLASS_LINK);
// verification & rewriting
// 验证&重写
{
oop init_lock = this_oop->init_lock();
ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
// rewritten will have been set if loader constraint error found
// on an earlier link attempt
// don't verify or rewrite if already rewritten
if (!this_oop->is_linked()) {
if (!this_oop->is_rewritten()) {
{
// Timer includes any side effects of class verification (resolution,
// etc), but not recursive entry into verify_code().
PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(),
ClassLoader::perf_class_verify_selftime(),
ClassLoader::perf_classes_verified(),
jt->get_thread_stat()->perf_recursion_counts_addr(),
jt->get_thread_stat()->perf_timers_addr(),
PerfClassTraceTime::CLASS_VERIFY);
// 验证:即字节码验证
bool verify_ok = verify_code(this_oop, throw_verifyerror, THREAD);
if (!verify_ok) {
return false;
}
}
// Just in case a side-effect of verify linked this class already
// (which can sometimes happen since the verifier loads classes
// using custom class loaders, which are free to initialize things)
if (this_oop->is_linked()) {
return true;
}
// also sets rewritten
// 重写:为支持更好的解释器运行性能,向常量池添加缓存,并调整相应字节码的常量池索引指向常量池Cache索引
this_oop->rewrite_class(CHECK_false);
}
// relocate jsrs and link methods after they are all rewritten
// 链接方法
this_oop->link_methods(CHECK_false);
// Initialize the vtable and interface table after
// methods have been rewritten since rewrite may
// fabricate new Method*s.
// also does loader constraint checking
// 由于方法被重写后会产生新的methodOops,在这里需要初始化虚函数表vtable和接口表itable
if (!this_oop()->is_shared()) {
ResourceMark rm(THREAD);
this_oop->vtable()->initialize_vtable(true, CHECK_false);
this_oop->itable()->initialize_itable(true, CHECK_false);
}
#ifdef ASSERT
else {
ResourceMark rm(THREAD);
this_oop->vtable()->verify(tty, true);
// In case itable verification is ever added.
// this_oop->itable()->verify(tty, true);
}
#endif
this_oop->set_init_state(linked);
if (JvmtiExport::should_post_class_prepare()) {
Thread *thread = THREAD;
assert(thread->is_Java_thread(), "thread->is_Java_thread()");
JvmtiExport::post_class_prepare((JavaThread *) thread, this_oop());
}
}
}
return true;
}
1. 验证
hotspot/src/share/vm/oops/instanceKlass.cpp
bool InstanceKlass::verify_code(
instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS) {
// 1) Verify the bytecodes
Verifier::Mode mode =
throw_verifyerror ? Verifier::ThrowException : Verifier::NoException;
return Verifier::verify(this_oop, mode, this_oop->should_verify_class(), CHECK_false);
}
hotspot/src/share/vm/classfile/verifier.cpp
bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool should_verify_class, TRAPS) {
HandleMark hm;
ResourceMark rm(THREAD);
Symbol* exception_name = NULL;
const size_t message_buffer_len = klass->name()->utf8_length() + 1024;
char* message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len);
char* exception_message = message_buffer;
const char* klassName = klass->external_name();
bool can_failover = FailOverToOldVerifier &&
klass->major_version() < NOFAILOVER_MAJOR_VERSION;
// If the class should be verified, first see if we can use the split
// verifier. If not, or if verification fails and FailOverToOldVerifier
// is set, then call the inference verifier.
if (is_eligible_for_verification(klass, should_verify_class)) {
if (TraceClassInitialization) {
tty->print_cr("Start class verification for: %s", klassName);
}
if (klass->major_version() >= STACKMAP_ATTRIBUTE_MAJOR_VERSION) {
ClassVerifier split_verifier(klass, THREAD);
split_verifier.verify_class(THREAD);
exception_name = split_verifier.result();
if (can_failover && !HAS_PENDING_EXCEPTION &&
(exception_name == vmSymbols::java_lang_VerifyError() ||
exception_name == vmSymbols::java_lang_ClassFormatError())) {
if (TraceClassInitialization || VerboseVerification) {
tty->print_cr(
"Fail over class verification to old verifier for: %s", klassName);
}
exception_name = inference_verify(
klass, message_buffer, message_buffer_len, THREAD);
}
if (exception_name != NULL) {
exception_message = split_verifier.exception_message();
}
} else {
exception_name = inference_verify(
klass, message_buffer, message_buffer_len, THREAD);
}
if (TraceClassInitialization || VerboseVerification) {
if (HAS_PENDING_EXCEPTION) {
tty->print("Verification for %s has", klassName);
tty->print_cr(" exception pending %s ",
InstanceKlass::cast(PENDING_EXCEPTION->klass())->external_name());
} else if (exception_name != NULL) {
tty->print_cr("Verification for %s failed", klassName);
}
tty->print_cr("End class verification for: %s", klassName);
}
}
if (HAS_PENDING_EXCEPTION) {
return false; // use the existing exception
} else if (exception_name == NULL) {
return true; // verifcation succeeded
} else { // VerifyError or ClassFormatError to be created and thrown
ResourceMark rm(THREAD);
instanceKlassHandle kls =
SystemDictionary::resolve_or_fail(exception_name, true, CHECK_false);
while (!kls.is_null()) {
if (kls == klass) {
// If the class being verified is the exception we're creating
// or one of it's superclasses, we're in trouble and are going
// to infinitely recurse when we try to initialize the exception.
// So bail out here by throwing the preallocated VM error.
THROW_OOP_(Universe::virtual_machine_error_instance(), false);
}
kls = kls->super();
}
message_buffer[message_buffer_len - 1] = '\0'; // just to be sure
THROW_MSG_(exception_name, exception_message, false);
}
}
2. 重写
hotspot/src/share/vm/oops/instanceKlass.cpp
void InstanceKlass::rewrite_class(TRAPS) {
assert(is_loaded(), "must be loaded");
instanceKlassHandle this_oop(THREAD, this);
if (this_oop->is_rewritten()) {
assert(this_oop()->is_shared(), "rewriting an unshared class?");
return;
}
Rewriter::rewrite(this_oop, CHECK);
this_oop->set_rewritten();
}
hotspot/src/share/vm/interpreter/rewriter.cpp
void Rewriter::rewrite(instanceKlassHandle klass, TRAPS) {
ResourceMark rm(THREAD);
Rewriter rw(klass, klass->constants(), klass->methods(), CHECK);
// (That's all, folks.)
}
Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array<Method*>* methods, TRAPS)
: _klass(klass),
_pool(cpool),
_methods(methods)
{
// Rewrite bytecodes - exception here exits.
rewrite_bytecodes(CHECK);
// Stress restoring bytecodes
if (StressRewriter) {
restore_bytecodes();
rewrite_bytecodes(CHECK);
}
// allocate constant pool cache, now that we've seen all the bytecodes
make_constant_pool_cache(THREAD);
// Restore bytecodes to their unrewritten state if there are exceptions
// rewriting bytecodes or allocating the cpCache
if (HAS_PENDING_EXCEPTION) {
restore_bytecodes();
return;
}
// Relocate after everything, but still do this under the is_rewritten flag,
// so methods with jsrs in custom class lists in aren't attempted to be
// rewritten in the RO section of the shared archive.
// Relocated bytecodes don't have to be restored, only the cp cache entries
int len = _methods->length();
for (int i = len-1; i >= 0; i--) {
methodHandle m(THREAD, _methods->at(i));
if (m->has_jsrs()) {
m = rewrite_jsrs(m, THREAD);
// Restore bytecodes to their unrewritten state if there are exceptions
// relocating bytecodes. If some are relocated, that is ok because that
// doesn't affect constant pool to cpCache rewriting.
if (HAS_PENDING_EXCEPTION) {
restore_bytecodes();
return;
}
// Method might have gotten rewritten.
methods->at_put(i, m());
}
}
}
三、初始化
hotspot/src/share/vm/oops/instanceKlass.cpp
void InstanceKlass::initialize(TRAPS) {
if (this->should_be_initialized()) {
HandleMark hm(THREAD);
instanceKlassHandle this_oop(THREAD, this);
initialize_impl(this_oop, CHECK);
// Note: at this point the class may be initialized
// OR it may be in the state of being initialized
// in case of recursive initialization!
} else {
assert(is_initialized(), "sanity check");
}
}
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
{
// 同步该类型对象instanceKlass,等待到当前线程可以获得instanceKlass锁
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
// 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.
// 如果此时还有别的线程正在初始化这个instanceKlass(状态:being_initialized),则对这个class对象wait
while(this_oop->is_being_initialized() && !this_oop->is_reentrant_initialization(self)) {
wait = true;
ol.waitUninterruptibly(CHECK);
}
// Step 3
// 如果当前线程正在对该类型初始化,则这一定是初始化的一个递归调用,此时释放class对象上的锁并正常地结束
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
// 如果类或接口已被初始化,则不再需要进一步动作,释放class对象上的锁并正常地结束
if (this_oop->is_initialized()) {
DTRACE_CLASSINIT_PROBE_WAIT(concurrent, InstanceKlass::cast(this_oop()), -1,wait);
return;
}
// Step 5
// 如果instanceKlass处于错误状态,则不可能初始化,释放class对象上的锁并抛出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
// 设置instanceKlass状态为being_initialized,并释放instanceKlass对象上的锁
this_oop->set_init_state(being_initialized);
this_oop->set_init_thread(self);
}
// Step 7
// 如果该instanceKlass对象表示的是一个类,且该类的父类未被初始化,则对父类递归执行初始化
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
// 除了final static变量和接口的其值为编译期常数的首先初始化外,按文本顺序执行类变量的初始化器和类的静态初始化函数,或者接口的域初始化器
// 具体实现在call_class_initializer
{
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
// 如果初始化函数的执行正常的结束,则锁定这个instanceKlass对象,并将其状态设置为fully_initialized
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
// 否则,抛出异常,如果e类型不是Error或其子类之一,则用e作为参数创建异常类ExceptionInInitializerError的一个新实例
// 接下来,锁定这个instanceKlass对象,把它标为initialization_error,通知所有正在等待的线程,最后抛出异常e
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);
}