jvm源码解读--06 Method 方法解析
进入
// 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
}
方法解析结束
jvm源码解读--06 Method 方法解析的更多相关文章
- jvm源码解读--16 cas 用法解析
CAS的意思是campare and sweep比较交换 这个如果不用代码会比较抽象,那么在源码中进行解释 void ATTR ObjectMonitor::enter(TRAPS) { // The ...
- JVM 源码解读之 CMS 何时会进行 Full GC
t点击上方"涤生的博客",关注我 转载请注明原创出处,谢谢!如果读完觉得有收获的话,欢迎点赞加关注. 前言 本文内容是基于 JDK 8 在文章 JVM 源码解读之 CMS GC 触 ...
- jvm源码解读--17 Java的wait()、notify()学习
write and debug by 张艳涛 wait()和notify()的通常用法 A线程取得锁,执行wait(),释放锁; B线程取得锁,完成业务后执行notify(),再释放锁; B线程释放锁 ...
- jvm源码解读--12 invokspecial指令的解读
先看代码 package com.zyt.jvmbook; public class Girl extends Person{ public Girl() { int a; } @Override p ...
- jvm源码解读--11 ldc指令的解读
写一个java文件 public static void main(String[] args) { String str1="abc"; String str2 ="a ...
- jvm源码解读--13 gc_root中的栈中oop的mark 和copy 过程分析
粘贴源码 package com.test; import java.util.Random; public class Test { static int number=12; private in ...
- jvm源码解读--08 创建oop对象,将static静态变量放置在oop的96 offset处
之前分析的已经加载的.Class文件中都没有Static 静态变量,所以也就没这部分的解析,自己也是不懂hotspot 将静态变量放哪里去了,追踪源码之后,看清楚了整个套路,总体上来说,可以举例来说对 ...
- Golang 源码解读 01、深入解析 strings.Builder、strings.Join
strings.Builder 源码解析. 存在意义. 实现原理. 常用方法. 写入方法. 扩容方法. String() 方法. 禁止复制. 线程不安全. io.Writer 接口. 代码. stri ...
- jvm源码解读--10 enum WKID 枚举
源码中对于枚举类型WKID的使用 static bool initialize_wk_klass(WKID id, int init_opt, TRAPS); static void initiali ...
随机推荐
- 【NX二次开发】移动WCS坐标系
说明:移动WCS坐标系 用法: #include <uf.h> #include <uf_csys.h> extern DllExport void ufusr(char *p ...
- python学习笔记04-了解操作符与条件分支
先来了解一下条件操作符: 运算符 描述 示例 == 检查两个操作数的值是否相等,如果是则条件变为真. 如a=3,b=3则(a == b) 为 true. != 检查两个操作数的值是否相等,如果值不相等 ...
- huge page 能给MySQL 带来性能提升吗?
最近一直在做性能压测相关的事情,有公众号的读者朋友咨询有赞的数据库服务器有没有开启huge page,我听说过huge page会对性能有所提升,本文就一探究竟.对过程没有兴趣的可以直接看结论. 二 ...
- Jenkins 进阶篇 - 节点配置
当我们使用 Jenkins 构建的项目达到一定规模后,一个 Jenkins 服务可能承受不了负载,会导致很多的构建任务堆积,严重的话还会拖垮这台服务器,导致上面的服务无法使用.例如我们公司目前在 Je ...
- php 安装 yii 报错: phpunit/phpunit 4.8.32 requires ext-dom *
php 安装 yii 报错: phpunit/phpunit 4.8.32 requires ext-dom * 我的版本是7.0,以7.0为例演示. 先装这两个拓展试试: sudo apt-get ...
- mycat高可用-安全管理-监控 看这一篇就够了
在之前的操作中,我们已经实现了mysql机器的高可用,可以动态切换master,那么如果mycat崩溃了呢?我们应该如何处理呢?所以此时就需要搭建mycat的高可用集群了. 在mycat的权威 ...
- C# DataGridView单元格画斜线
功能要求:不符合条件的单元格使用斜线形式表现出来. 1.定义两个变量,一个是存储单元格位置的数组,一个是Graphics 变量 Graphics gdi; List<DataGridViewCe ...
- Channel Allocation 贪心涂色
Channel Allocation 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> ...
- docker安装mysql镜像和容器
下拉镜像 docker pull mysql/mysql-server:5.5 后面的mysql标签是版本号,是可选择的,有: 5.5 5.6 5.7 8.0 创建mysql5.5的容器 docker ...
- 从 Java 代码到 Java 堆
本文将为您提供 Java 代码内存使用情况的深入见解,包括将 int 值置入一个 Integer 对象的内存开销.对象委托的成本和不同集合类型的内存效率.您将了解到如何确定应用程序中的哪些位置效率低下 ...