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 }
方法解析结束