进入
// 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,
&has_default_methods,
CHECK_(nullHandle));
接着进入
Array<Method*>* ClassFileParser::parse_methods(bool is_interface,
AccessFlags* promoted_flags,
bool* has_final_method,
bool* has_default_methods,
TRAPS) {
ClassFileStream* cfs = stream();
cfs->guarantee_more(2, CHECK_NULL); // length
u2 length = cfs->get_u2_fast(); //value=14 共14个方法
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);
if (method->is_final()) {
*has_final_method = true;
}
if (is_interface && !(*has_default_methods)
&& !method->is_abstract() && !method->is_static()
&& !method->is_private()) {
// default method
*has_default_methods = true;
}
_methods->at_put(index, method());
}
在进入
methodHandle ClassFileParser::parse_method(bool is_interface,
AccessFlags *promoted_flags,
TRAPS) {
ClassFileStream* cfs = stream();
methodHandle nullHandle;
ResourceMark rm(THREAD);
// Parse fixed parts
cfs->guarantee_more(8, CHECK_(nullHandle)); // access_flags, name_index, descriptor_index, attributes_count
int flags = cfs->get_u2_fast();
u2 name_index = cfs->get_u2_fast();
int cp_size = _cp->length();
check_property(
valid_symbol_at(name_index),
"Illegal constant pool index %u for method name in class file %s",
name_index, CHECK_(nullHandle));
Symbol* name = _cp->symbol_at(name_index);
verify_legal_method_name(name, CHECK_(nullHandle));
u2 signature_index = cfs->get_u2_fast();
guarantee_property(
valid_symbol_at(signature_index),
"Illegal constant pool index %u for method signature in class file %s",
signature_index, CHECK_(nullHandle));
Symbol* signature = _cp->symbol_at(signature_index);
AccessFlags access_flags;
if (name == vmSymbols::class_initializer_name()) {
// We ignore the other access flags for a valid class initializer.
// (JVM Spec 2nd ed., chapter 4.6)
if (_major_version < 51) { // backward compatibility
flags = JVM_ACC_STATIC;
} else if ((flags & JVM_ACC_STATIC) == JVM_ACC_STATIC) {
flags &= JVM_ACC_STATIC | JVM_ACC_STRICT;
}
} else {
verify_legal_method_modifiers(flags, is_interface, name, CHECK_(nullHandle));
}
int args_size = -1; // only used when _need_verify is true
if (_need_verify) {
args_size = ((flags & JVM_ACC_STATIC) ? 0 : 1) +
verify_legal_method_signature(name, signature, CHECK_(nullHandle));
if (args_size > MAX_ARGS_SIZE) {
classfile_parse_error("Too many arguments in method signature in class file %s", CHECK_(nullHandle));
}
}
access_flags.set_flags(flags & JVM_RECOGNIZED_METHOD_MODIFIERS);
// Default values for code and exceptions attribute elements
u2 max_stack = 0;
u2 max_locals = 0;
u4 code_length = 0;
u1* code_start = 0;
u2 exception_table_length = 0;
u2* exception_table_start = NULL;
Array<int>* exception_handlers = Universe::the_empty_int_array();
u2 checked_exceptions_length = 0;
u2* checked_exceptions_start = NULL;
CompressedLineNumberWriteStream* linenumber_table = NULL;
int linenumber_table_length = 0;
int total_lvt_length = 0;
u2 lvt_cnt = 0;
u2 lvtt_cnt = 0;
bool lvt_allocated = false;
u2 max_lvt_cnt = INITIAL_MAX_LVT_NUMBER;
u2 max_lvtt_cnt = INITIAL_MAX_LVT_NUMBER;
u2* localvariable_table_length;
u2** localvariable_table_start;
u2* localvariable_type_table_length;
u2** localvariable_type_table_start;
u2 method_parameters_length = 0;
u1* method_parameters_data = NULL;
bool method_parameters_seen = false;
bool parsed_code_attribute = false;
bool parsed_checked_exceptions_attribute = false;
bool parsed_stackmap_attribute = false;
// stackmap attribute - JDK1.5
u1* stackmap_data = NULL;
int stackmap_data_length = 0;
u2 generic_signature_index = 0;
MethodAnnotationCollector parsed_annotations;
u1* runtime_visible_annotations = NULL;
int runtime_visible_annotations_length = 0;
u1* runtime_invisible_annotations = NULL;
int runtime_invisible_annotations_length = 0;
u1* runtime_visible_parameter_annotations = NULL;
int runtime_visible_parameter_annotations_length = 0;
u1* runtime_invisible_parameter_annotations = NULL;
int runtime_invisible_parameter_annotations_length = 0;
u1* runtime_visible_type_annotations = NULL;
int runtime_visible_type_annotations_length = 0;
u1* runtime_invisible_type_annotations = NULL;
int runtime_invisible_type_annotations_length = 0;
bool runtime_invisible_type_annotations_exists = false;
u1* annotation_default = NULL;
int annotation_default_length = 0;
// Parse code and exceptions attribute
u2 method_attributes_count = cfs->get_u2_fast();
while (method_attributes_count--) {
cfs->guarantee_more(6, CHECK_(nullHandle)); // method_attribute_name_index, method_attribute_length
u2 method_attribute_name_index = cfs->get_u2_fast();
u4 method_attribute_length = cfs->get_u4_fast();
check_property(
valid_symbol_at(method_attribute_name_index),
"Invalid method attribute name index %u in class file %s",
method_attribute_name_index, CHECK_(nullHandle));
Symbol* method_attribute_name = _cp->symbol_at(method_attribute_name_index);
if (method_attribute_name == vmSymbols::tag_code()) {
// Parse Code attribute
if (_need_verify) {
guarantee_property(
!access_flags.is_native() && !access_flags.is_abstract(),
"Code attribute in native or abstract methods in class file %s",
CHECK_(nullHandle));
}
if (parsed_code_attribute) {
classfile_parse_error("Multiple Code attributes in class file %s", CHECK_(nullHandle));
}
parsed_code_attribute = true;
// Stack size, locals size, and code size
if (_major_version == 45 && _minor_version <= 2) {
cfs->guarantee_more(4, CHECK_(nullHandle));
max_stack = cfs->get_u1_fast();
max_locals = cfs->get_u1_fast();
code_length = cfs->get_u2_fast();
} else {
cfs->guarantee_more(8, CHECK_(nullHandle));
max_stack = cfs->get_u2_fast();
max_locals = cfs->get_u2_fast();
code_length = cfs->get_u4_fast();
}
if (_need_verify) {
guarantee_property(args_size <= max_locals,
"Arguments can't fit into locals in class file %s", CHECK_(nullHandle));
guarantee_property(code_length > 0 && code_length <= MAX_CODE_SIZE,
"Invalid method Code length %u in class file %s",
code_length, CHECK_(nullHandle));
}
// Code pointer
code_start = cfs->get_u1_buffer();
assert(code_start != NULL, "null code start");
cfs->guarantee_more(code_length, CHECK_(nullHandle));
cfs->skip_u1_fast(code_length);
// Exception handler table
cfs->guarantee_more(2, CHECK_(nullHandle)); // exception_table_length
exception_table_length = cfs->get_u2_fast();
if (exception_table_length > 0) {
exception_table_start =
parse_exception_table(code_length, exception_table_length, CHECK_(nullHandle));
}
// Parse additional attributes in code attribute
cfs->guarantee_more(2, CHECK_(nullHandle)); // code_attributes_count
u2 code_attributes_count = cfs->get_u2_fast();
unsigned int calculated_attribute_length = 0;
if (_major_version > 45 || (_major_version == 45 && _minor_version > 2)) {
calculated_attribute_length =
sizeof(max_stack) + sizeof(max_locals) + sizeof(code_length);
} else {
// max_stack, locals and length are smaller in pre-version 45.2 classes
calculated_attribute_length = sizeof(u1) + sizeof(u1) + sizeof(u2);
}
calculated_attribute_length +=
code_length +
sizeof(exception_table_length) +
sizeof(code_attributes_count) +
exception_table_length *
( sizeof(u2) + // start_pc
sizeof(u2) + // end_pc
sizeof(u2) + // handler_pc
sizeof(u2) ); // catch_type_index
while (code_attributes_count--) {
cfs->guarantee_more(6, CHECK_(nullHandle)); // code_attribute_name_index, code_attribute_length
u2 code_attribute_name_index = cfs->get_u2_fast();
u4 code_attribute_length = cfs->get_u4_fast();
calculated_attribute_length += code_attribute_length +
sizeof(code_attribute_name_index) +
sizeof(code_attribute_length);
check_property(valid_symbol_at(code_attribute_name_index),
"Invalid code attribute name index %u in class file %s",
code_attribute_name_index,
CHECK_(nullHandle));
if (LoadLineNumberTables &&
_cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_line_number_table()) {
// Parse and compress line number table
parse_linenumber_table(code_attribute_length, code_length,
&linenumber_table, CHECK_(nullHandle));
} else if (LoadLocalVariableTables &&
_cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_table()) {
// Parse local variable table
if (!lvt_allocated) {
localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2, INITIAL_MAX_LVT_NUMBER);
localvariable_table_start = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2*, INITIAL_MAX_LVT_NUMBER);
localvariable_type_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2, INITIAL_MAX_LVT_NUMBER);
localvariable_type_table_start = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2*, INITIAL_MAX_LVT_NUMBER);
lvt_allocated = true;
}
if (lvt_cnt == max_lvt_cnt) {
max_lvt_cnt <<= 1;
localvariable_table_length = REALLOC_RESOURCE_ARRAY(u2, localvariable_table_length, lvt_cnt, max_lvt_cnt);
localvariable_table_start = REALLOC_RESOURCE_ARRAY(u2*, localvariable_table_start, lvt_cnt, max_lvt_cnt);
}
localvariable_table_start[lvt_cnt] =
parse_localvariable_table(code_length,
max_locals,
code_attribute_length,
&localvariable_table_length[lvt_cnt],
false, // is not LVTT
CHECK_(nullHandle));
total_lvt_length += localvariable_table_length[lvt_cnt];
lvt_cnt++;
} else if (LoadLocalVariableTypeTables &&
_major_version >= JAVA_1_5_VERSION &&
_cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_type_table()) {
if (!lvt_allocated) {
localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2, INITIAL_MAX_LVT_NUMBER);
localvariable_table_start = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2*, INITIAL_MAX_LVT_NUMBER);
localvariable_type_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2, INITIAL_MAX_LVT_NUMBER);
localvariable_type_table_start = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2*, INITIAL_MAX_LVT_NUMBER);
lvt_allocated = true;
}
// Parse local variable type table
if (lvtt_cnt == max_lvtt_cnt) {
max_lvtt_cnt <<= 1;
localvariable_type_table_length = REALLOC_RESOURCE_ARRAY(u2, localvariable_type_table_length, lvtt_cnt, max_lvtt_cnt);
localvariable_type_table_start = REALLOC_RESOURCE_ARRAY(u2*, localvariable_type_table_start, lvtt_cnt, max_lvtt_cnt);
}
localvariable_type_table_start[lvtt_cnt] =
parse_localvariable_table(code_length,
max_locals,
code_attribute_length,
&localvariable_type_table_length[lvtt_cnt],
true, // is LVTT
CHECK_(nullHandle));
lvtt_cnt++;
} else if (_major_version >= Verifier::STACKMAP_ATTRIBUTE_MAJOR_VERSION &&
_cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_stack_map_table()) {
// Stack map is only needed by the new verifier in JDK1.5.
if (parsed_stackmap_attribute) {
classfile_parse_error("Multiple StackMapTable attributes in class file %s", CHECK_(nullHandle));
}
stackmap_data = parse_stackmap_table(code_attribute_length, CHECK_(nullHandle));
stackmap_data_length = code_attribute_length;
parsed_stackmap_attribute = true;
} else {
// Skip unknown attributes
cfs->skip_u1(code_attribute_length, CHECK_(nullHandle));
}
}
// check method attribute length
if (_need_verify) {
guarantee_property(method_attribute_length == calculated_attribute_length,
"Code segment has wrong length in class file %s", CHECK_(nullHandle));
}
} else if (method_attribute_name == vmSymbols::tag_exceptions()) {
// Parse Exceptions attribute
if (parsed_checked_exceptions_attribute) {
classfile_parse_error("Multiple Exceptions attributes in class file %s", CHECK_(nullHandle));
}
parsed_checked_exceptions_attribute = true;
checked_exceptions_start =
parse_checked_exceptions(&checked_exceptions_length,
method_attribute_length,
CHECK_(nullHandle));
} else if (method_attribute_name == vmSymbols::tag_method_parameters()) {
// reject multiple method parameters
if (method_parameters_seen) {
classfile_parse_error("Multiple MethodParameters attributes in class file %s", CHECK_(nullHandle));
}
method_parameters_seen = true;
method_parameters_length = cfs->get_u1_fast();
if (method_attribute_length != (method_parameters_length * 4u) + 1u) {
classfile_parse_error(
"Invalid MethodParameters method attribute length %u in class file",
method_attribute_length, CHECK_(nullHandle));
}
method_parameters_data = cfs->get_u1_buffer();
cfs->skip_u2_fast(method_parameters_length);
cfs->skip_u2_fast(method_parameters_length);
// ignore this attribute if it cannot be reflected
if (!SystemDictionary::Parameter_klass_loaded())
method_parameters_length = 0;
} else if (method_attribute_name == vmSymbols::tag_synthetic()) {
if (method_attribute_length != 0) {
classfile_parse_error(
"Invalid Synthetic method attribute length %u in class file %s",
method_attribute_length, CHECK_(nullHandle));
}
// Should we check that there hasn't already been a synthetic attribute?
access_flags.set_is_synthetic();
} else if (method_attribute_name == vmSymbols::tag_deprecated()) { // 4276120
if (method_attribute_length != 0) {
classfile_parse_error(
"Invalid Deprecated method attribute length %u in class file %s",
method_attribute_length, CHECK_(nullHandle));
}
} else if (_major_version >= JAVA_1_5_VERSION) {
if (method_attribute_name == vmSymbols::tag_signature()) {
if (method_attribute_length != 2) {
classfile_parse_error(
"Invalid Signature attribute length %u in class file %s",
method_attribute_length, CHECK_(nullHandle));
}
cfs->guarantee_more(2, CHECK_(nullHandle)); // generic_signature_index
generic_signature_index = cfs->get_u2_fast();
} else if (method_attribute_name == vmSymbols::tag_runtime_visible_annotations()) {
runtime_visible_annotations_length = method_attribute_length;
runtime_visible_annotations = cfs->get_u1_buffer();
assert(runtime_visible_annotations != NULL, "null visible annotations");
parse_annotations(runtime_visible_annotations,
runtime_visible_annotations_length, &parsed_annotations,
CHECK_(nullHandle));
cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle));
} else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
runtime_invisible_annotations_length = method_attribute_length;
runtime_invisible_annotations = cfs->get_u1_buffer();
assert(runtime_invisible_annotations != NULL, "null invisible annotations");
cfs->skip_u1(runtime_invisible_annotations_length, CHECK_(nullHandle));
} else if (method_attribute_name == vmSymbols::tag_runtime_visible_parameter_annotations()) {
runtime_visible_parameter_annotations_length = method_attribute_length;
runtime_visible_parameter_annotations = cfs->get_u1_buffer();
assert(runtime_visible_parameter_annotations != NULL, "null visible parameter annotations");
cfs->skip_u1(runtime_visible_parameter_annotations_length, CHECK_(nullHandle));
} else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_parameter_annotations()) {
runtime_invisible_parameter_annotations_length = method_attribute_length;
runtime_invisible_parameter_annotations = cfs->get_u1_buffer();
assert(runtime_invisible_parameter_annotations != NULL, "null invisible parameter annotations");
cfs->skip_u1(runtime_invisible_parameter_annotations_length, CHECK_(nullHandle));
} else if (method_attribute_name == vmSymbols::tag_annotation_default()) {
annotation_default_length = method_attribute_length;
annotation_default = cfs->get_u1_buffer();
assert(annotation_default != NULL, "null annotation default");
cfs->skip_u1(annotation_default_length, CHECK_(nullHandle));
} else if (method_attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) {
if (runtime_visible_type_annotations != NULL) {
classfile_parse_error(
"Multiple RuntimeVisibleTypeAnnotations attributes for method in class file %s",
CHECK_(nullHandle));
}
runtime_visible_type_annotations_length = method_attribute_length;
runtime_visible_type_annotations = cfs->get_u1_buffer();
assert(runtime_visible_type_annotations != NULL, "null visible type annotations");
// No need for the VM to parse Type annotations
cfs->skip_u1(runtime_visible_type_annotations_length, CHECK_(nullHandle));
} else if (method_attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) {
if (runtime_invisible_type_annotations_exists) {
classfile_parse_error(
"Multiple RuntimeInvisibleTypeAnnotations attributes for method in class file %s",
CHECK_(nullHandle));
} else {
runtime_invisible_type_annotations_exists = true;
}
if (PreserveAllAnnotations) {
runtime_invisible_type_annotations_length = method_attribute_length;
runtime_invisible_type_annotations = cfs->get_u1_buffer();
assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations");
}
cfs->skip_u1(method_attribute_length, CHECK_(nullHandle));
} else {
// Skip unknown attributes
cfs->skip_u1(method_attribute_length, CHECK_(nullHandle));
}
} else {
// Skip unknown attributes
cfs->skip_u1(method_attribute_length, CHECK_(nullHandle));
}
}
if (linenumber_table != NULL) {
linenumber_table->write_terminator();
linenumber_table_length = linenumber_table->position();
}
// Make sure there's at least one Code attribute in non-native/non-abstract method
if (_need_verify) {
guarantee_property(access_flags.is_native() || access_flags.is_abstract() || parsed_code_attribute,
"Absent Code attribute in method that is not native or abstract in class file %s", CHECK_(nullHandle));
}
// All sizing information for a Method* is finally available, now create it
InlineTableSizes sizes(
total_lvt_length,
linenumber_table_length,
exception_table_length,
checked_exceptions_length,
method_parameters_length,
generic_signature_index,
runtime_visible_annotations_length +
runtime_invisible_annotations_length,
runtime_visible_parameter_annotations_length +
runtime_invisible_parameter_annotations_length,
runtime_visible_type_annotations_length +
runtime_invisible_type_annotations_length,
annotation_default_length,
0);
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
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;
}
//方法解析之前先看下,结构
ClassFile {
...
u2 methods_count;
method_info methods[methods_count];
};
method_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
};
attribute_info {
u2 attribute_name_index;
u4 attribute_length;
u1 info[attribute_length];
}
//查询出来的Symbol是Code,则看Code的定义
4.7.3 The Code Attribute
The Code attribute has the following format:
Code_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 max_stack;
u2 max_locals;
u4 code_length;
u1 code[code_length];
u2 exception_table_length;
{ u2 start_pc;
u2 end_pc;
u2 handler_pc;
u2 catch_type;
} exception_table[exception_table_length];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
进入这个长长的方法之后,我们逐条解析
int flags = cfs->get_u2_fast(); //flag=1
u2 name_index = cfs->get_u2_fast(); //name_index 19
int cp_size = _cp->length(); //cp_size=87
Symbol* name = _cp->symbol_at(name_index); //(gdb) p name->as_C_string() $1 = 0x7fb9b000f138 "<init>"
u2 signature_index = cfs->get_u2_fast(); //value=20
Symbol* signature = _cp->symbol_at(signature_index); //$2 = 0x7fb9b000f148 "()V"
接着
AccessFlags access_flags;
if (name == vmSymbols::class_initializer_name()) {
// We ignore the other access flags for a valid class initializer.
// (JVM Spec 2nd ed., chapter 4.6)
if (_major_version < 51) { // backward compatibility
flags = JVM_ACC_STATIC;
} else if ((flags & JVM_ACC_STATIC) == JVM_ACC_STATIC) {
flags &= JVM_ACC_STATIC | JVM_ACC_STRICT;
}
} else {
verify_legal_method_modifiers(flags, is_interface, name, CHECK_(nullHandle));
}
对标记的进行解析,由于这个是一个宏
VM_SYMBOLS_DO(VM_SYMBOL_DECLARE, VM_SYMBOL_DECLARE)
VM_SYMBOL_DECLARE(object_initializer_name, "<init>")
#define VM_SYMBOL_DECLARE(name, ignore) \
static Symbol* name() { \
return _symbols[VM_SYMBOL_ENUM_NAME(name)]; \
}
#define VM_SYMBOL_ENUM_NAME(name) name##_enum //注意##为链接符号
static Symbol* object_initializer_name() {
return _symbols[object_initializer_name_enum];
}
解析后
enum SID {
NO_SID = 0,
/* commonly used class names */
java_lang_System_enum,
java_lang_Object_enum,
java_lang_Class_enum,
java_lang_String_enum,
java_lang_StringValue_enum,
java_lang_StringCache_enum,
java_lang_Thread_enum,
java_lang_ThreadGroup_enum,
java_lang_Cloneable_enum,
java_lang_Throwable_enum,
java_lang_ClassLoader_enum,
java_lang_ClassLoader_NativeLibrary_enum,
java_lang_ThreadDeath_enum,
java_lang_Boolean_enum,
java_lang_Character_enum,
java_lang_Character_CharacterCache_enum,
java_lang_Float_enum,
java_lang_Double_enum,
java_lang_Byte_enum,
java_lang_Byte_Cache_enum,
java_lang_Short_enum,
java_lang_Short_ShortCache_enum,
java_lang_Integer_enum,
java_lang_Integer_IntegerCache_enum,
java_lang_Long_enum,
java_lang_Long_LongCache_enum,
java_lang_Shutdown_enum,
java_lang_ref_Reference_enum,
java_lang_ref_SoftReference_enum,
java_lang_ref_WeakReference_enum,
java_lang_ref_FinalReference_enum,
java_lang_ref_PhantomReference_enum,
sun_misc_Cleaner_enum,
java_lang_ref_Finalizer_enum,
java_lang_reflect_AccessibleObject_enum,
java_lang_reflect_Method_enum,
java_lang_reflect_Constructor_enum,
java_lang_reflect_Field_enum,
java_lang_reflect_Array_enum,
java_lang_StringBuffer_enum,
java_lang_StringBuilder_enum,
java_lang_CharSequence_enum,
java_security_AccessControlContext_enum,
java_security_ProtectionDomain_enum,
impliesCreateAccessControlContext_name_enum,
java_io_OutputStream_enum,
java_io_Reader_enum,
java_io_BufferedReader_enum,
java_io_FileInputStream_enum,
java_io_ByteArrayInputStream_enum,
java_io_Serializable_enum,
java_util_Arrays_enum,
java_util_Properties_enum,
java_util_Vector_enum,
java_util_AbstractList_enum,
java_util_Hashtable_enum,
java_util_HashMap_enum,
java_lang_Compiler_enum,
sun_misc_Signal_enum,
java_lang_AssertionStatusDirectives_enum,
sun_jkernel_DownloadManager_enum,
getBootClassPathEntryForClass_name_enum,
sun_misc_PostVMInitHook_enum,
/* class file format tags */
tag_source_file_enum,
tag_inner_classes_enum,
tag_constant_value_enum,
tag_code_enum,
tag_exceptions_enum,
tag_line_number_table_enum,
tag_local_variable_table_enum,
tag_local_variable_type_table_enum,
tag_stack_map_table_enum,
tag_synthetic_enum,
tag_deprecated_enum,
tag_source_debug_extension_enum,
tag_signature_enum,
tag_runtime_visible_annotations_enum,
tag_runtime_invisible_annotations_enum,
tag_runtime_visible_parameter_annotations_enum,
tag_runtime_invisible_parameter_annotations_enum,
tag_annotation_default_enum,
tag_enclosing_method_enum,
tag_bootstrap_methods_enum,
/* exception klasses: at least all exceptions thrown by the VM have entries here */
java_lang_ArithmeticException_enum,
java_lang_ArrayIndexOutOfBoundsException_enum,
java_lang_ArrayStoreException_enum,
java_lang_ClassCastException_enum,
java_lang_ClassNotFoundException_enum,
java_lang_CloneNotSupportedException_enum,
java_lang_IllegalAccessException_enum,
java_lang_IllegalArgumentException_enum,
java_lang_IllegalStateException_enum,
java_lang_IllegalMonitorStateException_enum,
java_lang_IllegalThreadStateException_enum,
java_lang_IndexOutOfBoundsException_enum,
java_lang_InstantiationException_enum,
java_lang_InstantiationError_enum,
java_lang_InterruptedException_enum,
java_lang_BootstrapMethodError_enum,
java_lang_LinkageError_enum,
java_lang_NegativeArraySizeException_enum,
java_lang_NoSuchFieldException_enum,
java_lang_NoSuchMethodException_enum,
java_lang_NullPointerException_enum,
java_lang_StringIndexOutOfBoundsException_enum,
java_lang_InvalidClassException_enum,
java_lang_reflect_InvocationTargetException_enum,
java_lang_Exception_enum,
java_lang_RuntimeException_enum,
java_io_IOException_enum,
java_security_PrivilegedActionException_enum,
/* error klasses: at least all errors thrown by the VM have entries here */
java_lang_AbstractMethodError_enum,
java_lang_ClassCircularityError_enum,
java_lang_ClassFormatError_enum,
java_lang_UnsupportedClassVersionError_enum,
java_lang_Error_enum,
java_lang_ExceptionInInitializerError_enum,
java_lang_IllegalAccessError_enum,
java_lang_IncompatibleClassChangeError_enum,
java_lang_InternalError_enum,
java_lang_NoClassDefFoundError_enum,
java_lang_NoSuchFieldError_enum,
java_lang_NoSuchMethodError_enum,
java_lang_OutOfMemoryError_enum,
java_lang_UnsatisfiedLinkError_enum,
java_lang_VerifyError_enum,
java_lang_SecurityException_enum,
java_lang_VirtualMachineError_enum,
java_lang_StackOverflowError_enum,
java_lang_StackTraceElement_enum,
java_util_concurrent_locks_AbstractOwnableSynchronizer_enum,
sun_reflect_FieldInfo_enum,
sun_reflect_MethodInfo_enum,
sun_reflect_MagicAccessorImpl_enum,
sun_reflect_MethodAccessorImpl_enum,
sun_reflect_ConstructorAccessorImpl_enum,
sun_reflect_SerializationConstructorAccessorImpl_enum,
sun_reflect_DelegatingClassLoader_enum,
sun_reflect_Reflection_enum,
checkedExceptions_name_enum,
clazz_name_enum,
exceptionTypes_name_enum,
modifiers_name_enum,
newConstructor_name_enum,
newConstructor_signature_enum,
newField_name_enum,
newField_signature_enum,
newMethod_name_enum,
newMethod_signature_enum,
/* the following two names must be in order: */
invokeExact_name_enum,
invokeGeneric_name_enum,
invokeVarargs_name_enum,
star_name_enum, /*not really a name*/
invoke_name_enum,
override_name_enum,
parameterTypes_name_enum,
returnType_name_enum,
signature_name_enum,
slot_name_enum,
selectAlternative_name_enum,
/* Support for annotations (JDK 1.5 and above) */
annotations_name_enum,
parameter_annotations_name_enum,
annotation_default_name_enum,
sun_reflect_ConstantPool_enum,
constantPoolOop_name_enum,
sun_reflect_UnsafeStaticFieldAccessorImpl_enum,
base_name_enum,
/* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */
java_lang_invoke_InvokeDynamic_enum,
java_lang_invoke_Linkage_enum,
java_lang_invoke_CallSite_enum,
java_lang_invoke_ConstantCallSite_enum,
java_lang_invoke_MutableCallSite_enum,
java_lang_invoke_VolatileCallSite_enum,
java_lang_invoke_MethodHandle_enum,
java_lang_invoke_MethodType_enum,
java_lang_invoke_WrongMethodTypeException_enum,
java_lang_invoke_MethodType_signature_enum,
java_lang_invoke_MethodHandle_signature_enum,
/* internal classes known only to the JVM: */
java_lang_invoke_MethodTypeForm_enum,
java_lang_invoke_MethodTypeForm_signature_enum,
java_lang_invoke_MemberName_enum,
java_lang_invoke_MethodHandleNatives_enum,
java_lang_invoke_MethodHandleImpl_enum,
java_lang_invoke_AdapterMethodHandle_enum,
java_lang_invoke_BoundMethodHandle_enum,
java_lang_invoke_DirectMethodHandle_enum,
java_lang_invoke_CountingMethodHandle_enum,
/* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */
findMethodHandleType_name_enum,
findMethodHandleType_signature_enum,
notifyGenericMethodType_name_enum,
notifyGenericMethodType_signature_enum,
linkMethodHandleConstant_name_enum,
linkMethodHandleConstant_signature_enum,
makeDynamicCallSite_name_enum,
makeDynamicCallSite_signature_enum,
setTargetNormal_name_enum,
setTargetVolatile_name_enum,
setTarget_signature_enum,
selectAlternative_signature_enum,
/* common method and field names */
object_initializer_name_enum,
class_initializer_name_enum,
println_name_enum,
printStackTrace_name_enum,
main_name_enum,
name_name_enum,
priority_name_enum,
stillborn_name_enum,
group_name_enum,
daemon_name_enum,
eetop_name_enum,
thread_status_name_enum,
run_method_name_enum,
exit_method_name_enum,
add_method_name_enum,
remove_method_name_enum,
parent_name_enum,
threads_name_enum,
groups_name_enum,
maxPriority_name_enum,
destroyed_name_enum,
vmAllowSuspension_name_enum,
nthreads_name_enum,
ngroups_name_enum,
shutdown_method_name_enum,
finalize_method_name_enum,
reference_lock_name_enum,
reference_discovered_name_enum,
run_finalization_name_enum,
run_finalizers_on_exit_name_enum,
uncaughtException_name_enum,
dispatchUncaughtException_name_enum,
initializeSystemClass_name_enum,
loadClass_name_enum,
loadClassInternal_name_enum,
get_name_enum,
put_name_enum,
type_name_enum,
findNative_name_enum,
deadChild_name_enum,
addClass_name_enum,
getFromClass_name_enum,
dispatch_name_enum,
getSystemClassLoader_name_enum,
fillInStackTrace_name_enum,
fillInStackTrace0_name_enum,
getCause_name_enum,
initCause_name_enum,
setProperty_name_enum,
getProperty_name_enum,
context_name_enum,
privilegedContext_name_enum,
contextClassLoader_name_enum,
inheritedAccessControlContext_name_enum,
isPrivileged_name_enum,
isAuthorized_name_enum,
wait_name_enum,
checkPackageAccess_name_enum,
stackSize_name_enum,
thread_id_name_enum,
newInstance0_name_enum,
limit_name_enum,
forName_name_enum,
forName0_name_enum,
isJavaIdentifierStart_name_enum,
isJavaIdentifierPart_name_enum,
exclusive_owner_thread_name_enum,
park_blocker_name_enum,
park_event_name_enum,
cache_field_name_enum,
value_name_enum,
offset_name_enum,
count_name_enum,
hash_name_enum,
frontCacheEnabled_name_enum,
stringCacheEnabled_name_enum,
numberOfLeadingZeros_name_enum,
numberOfTrailingZeros_name_enum,
bitCount_name_enum,
profile_name_enum,
equals_name_enum,
target_name_enum,
toString_name_enum,
values_name_enum,
receiver_name_enum,
vmmethod_name_enum,
vmtarget_name_enum,
vmentry_name_enum,
vmcount_name_enum,
vmslots_name_enum,
vmlayout_name_enum,
vmindex_name_enum,
vmargslot_name_enum,
flags_name_enum,
argument_name_enum,
conversion_name_enum,
rtype_name_enum,
ptypes_name_enum,
form_name_enum,
erasedType_name_enum,
genericInvoker_name_enum,
append_name_enum,
klass_name_enum,
resolved_constructor_name_enum,
array_klass_name_enum,
oop_size_name_enum,
static_oop_field_count_name_enum,
...省略 若干
FIRST_SID = NO_SID + 1
};
接着
/接着
// Parse code and exceptions attribute
u2 method_attributes_count = cfs->get_u2_fast();
while (method_attributes_count--) {
cfs->guarantee_more(6, CHECK_(nullHandle)); // method_attribute_name_index, method_attribute_length
u2 method_attribute_name_index = cfs->get_u2_fast(); //value=21
u4 method_attribute_length = cfs->get_u4_fast(); //value =43
check_property(
valid_symbol_at(method_attribute_name_index),
"Invalid method attribute name index %u in class file %s",
method_attribute_name_index, CHECK_(nullHandle));
//调用了_cp对象的方法
Symbol* method_attribute_name = _cp->symbol_at(method_attribute_name_index);//arg=21,
//(gdb) p method_attribute_name->as_C_string()
//$6 = 0x7f7a7c00f148 "Code"
Symbol* symbol_at(int which) {
assert(tag_at(which).is_utf8(), "Corrupted constant pool");
return *symbol_at_addr(which);
}
Symbol** symbol_at_addr(int which) const {
assert(is_within_bounds(which), "index out of bounds");
return (Symbol**) &base()[which];
}
intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(ConstantPool)); }
(gdb) p this
$5 = (const ConstantPool * const) 0x7f7a6ab8c108
很多内容都是解析,省略
接着进入创建Method与ConstMethod对象
// All sizing information for a Method* is finally available, now create it
InlineTableSizes sizes(
total_lvt_length,
linenumber_table_length,
exception_table_length,
checked_exceptions_length,
method_parameters_length,
generic_signature_index,
runtime_visible_annotations_length +
runtime_invisible_annotations_length,
runtime_visible_parameter_annotations_length +
runtime_invisible_parameter_annotations_length,
runtime_visible_type_annotations_length +
runtime_invisible_type_annotations_length,
annotation_default_length,
0);
Method* m = Method::allocate(
_loader_data, code_length, access_flags, &sizes,
ConstMethod::NORMAL, CHECK_(nullHandle));
其中的InlineTableSizes sizes(xx,xx,xx,xx)是构造方法,有点没看出来,因为这里类是宏定义的解析完之后的为
解析完之后的为
(gdb) ptype InlineTableSizes
type = class InlineTableSizes : private StackObj {
private:
int _localvariable_table_length;
int _compressed_linenumber_size;
int _exception_table_length;
int _checked_exceptions_length;
int _method_parameters_length;
int _generic_signature_index;
int _method_annotations_length;
int _parameter_annotations_length;
int _type_annotations_length;
int _default_annotations_length;
int _end;
public:
InlineTableSizes(int, int, int, int, int, int, int, int, int, int, int):{}
InlineTableSizes(void);
int localvariable_table_length(void) const;
int compressed_linenumber_size(void) const;
int exception_table_length(void) const;
int checked_exceptions_length(void) const;
int method_parameters_length(void) const;
int generic_signature_index(void) const;
int method_annotations_length(void) const;
int parameter_annotations_length(void) const;
int type_annotations_length(void) const;
int default_annotations_length(void) const;
}
解析构造方法:解析过程如下
InlineTableSizes(
INLINE_TABLES_DO(INLINE_TABLE_PARAM)
int end) :
INLINE_TABLES_DO(INLINE_TABLE_INIT)
_end(end) {}
#define INLINE_TABLES_DO(do_element) \
do_element(localvariable_table_length) \
do_element(compressed_linenumber_size) \
do_element(exception_table_length) \
do_element(checked_exceptions_length) \
do_element(method_parameters_length) \
do_element(generic_signature_index) \
do_element(method_annotations_length) \
do_element(parameter_annotations_length) \
do_element(type_annotations_length) \
do_element(default_annotations_length)
#define INLINE_TABLE_INIT(sym) _##sym(sym),
代换
InlineTableSizes() :
INLINE_TABLE_INIT(localvariable_table_length)
INLINE_TABLE_INIT(compressed_linenumber_size)
INLINE_TABLE_INIT(compressed_linenumber_size)
INLINE_TABLE_INIT(exception_table_length)
INLINE_TABLE_INIT(checked_exceptions_length)
INLINE_TABLE_INIT(method_parameters_length)
INLINE_TABLE_INIT(generic_signature_index)
INLINE_TABLE_INIT(method_annotations_length)
INLINE_TABLE_INIT(parameter_annotations_length)
INLINE_TABLE_INIT(type_annotations_length)
INLINE_TABLE_INIT(default_annotations_length)
_end(end) {}
代换第二层
InlineTableSizes(int localvariable_table_length,
int compressed_linenumber_size,
int exception_table_length,
int checked_exceptions_length,
int method_parameters_length,
int generic_signature_index,
int method_annotations_length,
int parameter_annotations_length,
int type_annotations_length,
int default_annotations_length
) :
_localvariable_table_length(localvariable_table_length),
_compressed_linenumber_size(compressed_linenumber_size),
_compressed_linenumber_size(compressed_linenumber_size),
_exception_table_length(exception_table_length),
_checked_exceptions_length(checked_exceptions_length),
_method_parameters_length(method_parameters_length),
_generic_signature_index(generic_signature_index),
_method_annotations_length(method_annotations_length),
_parameter_annotations_length(parameter_annotations_length),
_type_annotations_length(type_annotations_length),
_default_annotations_length(default_annotations_length),
_end(end) {}
//接着进入流程
//接着进入流程
Method* Method::allocate(ClassLoaderData* loader_data,
int byte_code_size,
AccessFlags access_flags,
InlineTableSizes* sizes,
ConstMethod::MethodType method_type,
TRAPS) {
assert(!access_flags.is_native() || byte_code_size == 0,
"native methods should not contain byte codes");
ConstMethod* cm = ConstMethod::allocate(loader_data,
byte_code_size,
sizes,
method_type,
CHECK_NULL);
int size = Method::size(access_flags.is_native());
return new (loader_data, size, false, MetaspaceObj::MethodType, THREAD) Method(cm, access_flags, size);
}
标记的有点意思
int ConstMethod::size(int code_size,InlineTableSizes* sizes) {
int extra_bytes = code_size;
if (sizes->compressed_linenumber_size() > 0) {
extra_bytes += sizes->compressed_linenumber_size();
}
if (sizes->checked_exceptions_length() > 0) {
extra_bytes += sizeof(u2);
extra_bytes += sizes->checked_exceptions_length() * sizeof(CheckedExceptionElement);
}
if (sizes->localvariable_table_length() > 0) {
extra_bytes += sizeof(u2);
extra_bytes += sizes->localvariable_table_length() * sizeof(LocalVariableTableElement);
}
if (sizes->exception_table_length() > 0) {
extra_bytes += sizeof(u2);
extra_bytes += sizes->exception_table_length() * sizeof(ExceptionTableElement);
}
if (sizes->generic_signature_index() != 0) {
extra_bytes += sizeof(u2);
}
if (sizes->method_parameters_length() > 0) {
extra_bytes += sizeof(u2);
extra_bytes += sizes->method_parameters_length() * sizeof(MethodParametersElement);
}
// Align sizes up to a word.
extra_bytes = align_size_up(extra_bytes, BytesPerWord);
// One pointer per annotation array
if (sizes->method_annotations_length() > 0) {
extra_bytes += sizeof(AnnotationArray*);
}
if (sizes->parameter_annotations_length() > 0) {
extra_bytes += sizeof(AnnotationArray*);
}
if (sizes->type_annotations_length() > 0) {
extra_bytes += sizeof(AnnotationArray*);
}
if (sizes->default_annotations_length() > 0) {
extra_bytes += sizeof(AnnotationArray*);
}
int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord;
return align_object_size(header_size() + extra_words); // 内存大小的单位为字
}
static int header_size() {
return sizeof(ConstMethod)/HeapWordSize;
}
所以有俩部分,一部分是ConstMethod 的sizeof 另外一部分就是Code字节码和InlineTableSizes的内容
分布图如
/////////////////////////////////////
/ ConstantMethod /
/ --------------------------------/
Code
---------------------------------
localvariable_table_length / 这个属性 Object 没有
---------------------------------
compressed_linenumber_size
--------------------------------
打印内存内容
参数
set print pretty on 格式化c结构体输出
(gdb) set print pretty on
(gdb) p *sizes
$13 = (InlineTableSizes) {
<StackObj> = {
<AllocatedObj> = {
_vptr.AllocatedObj = 0x7f7a81c5c8f0 <vtable for InlineTableSizes+16>
}, <No data fields>},
members of InlineTableSizes:
_localvariable_table_length = 1,
_compressed_linenumber_size = 4,
_exception_table_length = 0,
_checked_exceptions_length = 0,
_method_parameters_length = 0,
_generic_signature_index = 0,
_method_annotations_length = 0,
_parameter_annotations_length = 0,
_type_annotations_length = 0,
_default_annotations_length = 0,
_end = 0
}
//当创建cm对象之后,打印
(gdb) p cm
$14 = (ConstMethod *) 0x7f7a6ab8c4a8
(gdb) p * cm
$15 = {
<MetaspaceObj> = {<No data fields>},
members of ConstMethod:
_fingerprint = 9223372036854775808,
_constants = 0x0,
_stackmap_data = 0x0,
_constMethod_size = 9,
_flags = 5,
_code_size = 1,
_name_index = 0,
_signature_index = 0,
_method_idnum = 0,
_max_stack = 0,
_max_locals = 0,
_size_of_parameters = 0,
static MAX_IDNUM = 65534,
static UNSET_IDNUM = 65535
}
给Method 创建对象
int size = Method::size(access_flags.is_native()); //size=12
//进入方法
int Method::size(bool is_native) { //false
// If native, then include pointers for native_function and signature_handler
int extra_bytes = (is_native) ? 2*sizeof(address*) : 0;
int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord;
return align_object_size(header_size() + extra_words);
}
static int header_size(){ return sizeof(Method)/HeapWordSize; }
打印对象
(gdb) p m
$26 = (Method *) 0x7f7a6ab8c4f0
(gdb) p * m
$27 = (Method) {
<Metadata> = {
<MetaspaceObj> = {<No data fields>},
members of Metadata:
_vptr.Metadata = 0x7f7a81c84b90 <vtable for Method+16>,
_valid = 0
},
members of Method:
_constMethod = 0x7f7a6ab8c4a8,
_method_data = 0x0,
_method_counters = 0x0,
_access_flags = {
_flags = 1
},
_vtable_index = -3,
_method_size = 12,
_intrinsic_id = 0 '\000',
_jfr_towrite = 0 '\000',
_caller_sensitive = 0 '\000',
_force_inline = 0 '\000',
_hidden = 0 '\000',
_dont_inline = 0 '\000',
_compiled_invocation_count = 0,
_i2i_entry = 0x0,
_adapter = 0x0,
_from_compiled_entry = 0x0,
_code = 0x0,
_from_interpreted_entry = 0x0,
static extra_stack_entries_for_jsr292 = 1
}
接着进入对象的属性设置
ClassLoadingService::add_class_method_size(m->size()*HeapWordSize);
// Copy byte codes
m->set_code(code_start);
// byte codes
void set_code(address code) { return constMethod()->set_code(code); }
void set_code(address code) {
if (code_size() > 0) {
memcpy(code_base(), code, code_size());
}
}
address code_base() const { return (address) (this+1); }
这里有点意思
(gdb) p this
$3 = (const ConstMethod * const) 0x7f950f4304a8
(gdb) p this +1 //注意,这里取的是COde字节码
$4 = (const ConstMethod * const) 0x7f950f4304d8
(gdb) p sizeof(*this)
$5 = 320
注意的是this +1 ,因为this 类型ConstMethod那么+1 就加上320个字节,那么就是在对象后面的第一个字节
最后打印对象
(gdb) p * m
$11 = (Method) {
<Metadata> = {
<MetaspaceObj> = {<No data fields>},
members of Metadata:
_vptr.Metadata = 0x7f9532845b90 <vtable for Method+16>,
_valid = 0
},
members of Method:
_constMethod = 0x7f950f4304a8,
_method_data = 0x0,
_method_counters = 0x0,
_access_flags = {
_flags = 1
},
_vtable_index = -3,
_method_size = 12,
_intrinsic_id = 0 '\000',
_jfr_towrite = 0 '\000',
_caller_sensitive = 0 '\000',
_force_inline = 0 '\000',
_hidden = 0 '\000',
_dont_inline = 0 '\000',
_compiled_invocation_count = 0,
_i2i_entry = 0x0,
_adapter = 0x0,
_from_compiled_entry = 0x0,
_code = 0x0,
_from_interpreted_entry = 0x0,
static extra_stack_entries_for_jsr292 = 1
}
(gdb) p * m->constMethod()
$12 = {
<MetaspaceObj> = {<No data fields>},
members of ConstMethod:
_fingerprint = 9223372036854775808,
_constants = 0x7f950f430108,
_stackmap_data = 0x0,
_constMethod_size = 9,
_flags = 5,
_code_size = 1,
_name_index = 19,
_signature_index = 20,
_method_idnum = 0,
_max_stack = 0,
_max_locals = 1,
_size_of_parameters = 1,
static MAX_IDNUM = 65534,
static UNSET_IDNUM = 65535
}
方法解析结束