JVM类解析之方法解析(三)

320 阅读12分钟

JVM解析方法的代码如下:

Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,bool is_interface,
const ConstantPool* cp, AccessFlags* const promoted_flags,  TRAPS){
   ...
}

JVM的字节码的方法访问标识和名称

image.png

1。首先创建ResourceMark记录当前Thread的resouceArea的资源使用,以便在析构函数时候释放资源空间.

  ResourceMark rm(THREAD);

2. 对解析的方法的access_flags和name_index以及signature_index做校验。

  //解析字节码流的2个字节的方法的access_flags
  int flags = cfs->get_u2_fast();
  //解析字节码流的2个字节的方法的name_index
  const u2 name_index = cfs->get_u2_fast();
   //获取常量池的长度,
  const 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_NULL);
  // 获取常量池中name_index对应符号对象Symbol
  const Symbol* const name = cp->symbol_at(name_index);
  // 对应方法名称做校验
  verify_legal_method_name(name, CHECK_NULL);
  // 解析字节码流的2个字节的方法的signature_index
  const u2 signature_index = cfs->get_u2_fast();
  // 对signature_index做长度校验
  guarantee_property(
    valid_symbol_at(signature_index),
    "Illegal constant pool index %u for method signature in class file %s",signature_index, CHECK_NULL);
   // 获取signature_index的方法签名的符号对象
  const Symbol* const signature = cp->symbol_at(signature_index);

3. 判断方法名称等于'clinit',则是类的初始化, 则校验方法的access_flags。

  if (name == vmSymbols::class_initializer_name()) {

    if (_major_version < 51) { // backward compatibility
      flags = JVM_ACC_STATIC;
    } else if ((flags & JVM_ACC_STATIC) == JVM_ACC_STATIC) {
      flags &= JVM_ACC_STATIC | (_major_version <= JAVA_16_VERSION ? JVM_ACC_STRICT : 0);
    } else {
      classfile_parse_error("Method <clinit> is not static in class file %s", THREAD);
      return NULL;
    }
  } else {
    verify_legal_method_modifiers(flags, is_interface, name, CHECK_NULL);
  }

4. 如果是接口并且方法名等于'init', 抛出接口不能有init的异常。

  if (name == vmSymbols::object_initializer_name() && is_interface) {
    classfile_parse_error("Interface cannot have a method named <init>, class file %s", THREAD);
    return NULL;
  }

5. 校验方法的名称和签名。

  int args_size = -1; 
  if (_need_verify) {
    verify_legal_name_with_signature(name, signature, CHECK_NULL);
    // 如果静态字段
    args_size = ((flags & JVM_ACC_STATIC) ? 0 : 1) +
                 verify_legal_method_signature(name, signature, CHECK_NULL);
    if (args_size > MAX_ARGS_SIZE) {
      classfile_parse_error("Too many arguments in method signature in class file %s", THREAD);
      return NULL;
    }
  }
  //创建AccessFlags对象
  AccessFlags access_flags(flags & JVM_RECOGNIZED_METHOD_MODIFIERS);

解析方法字节码指令和异常属性

  1. 解析方法的字节码指令和异常属性。
   //获取2个字节的方法属性个数
  u2 method_attributes_count = cfs->get_u2_fast();
  //开始遍历解析方法的属性
    while (method_attributes_count--) {
    cfs->guarantee_more(6, CHECK_NULL);
    // 获取2个字节的方法的属性的名称的常量池索引
    const u2 method_attribute_name_index = cfs->get_u2_fast();
    //获取2个字节的方法的属性的长度
    const u4 method_attribute_length = cfs->get_u4_fast();
    // 获取常量池中方法属性索引的名称的符号
    const Symbol* const method_attribute_name = cp->symbol_at(method_attribute_name_index);
    // 判断方法属性的名称是否等于'Code'
    if (method_attribute_name == vmSymbols::tag_code()) {
    // 校验native和abstract是没有Code属性的
      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_NULL);
      }
      //判断是否存在重复解析Code属性
      if (parsed_code_attribute) {
        classfile_parse_error("Multiple Code attributes in class file %s",  THREAD);
        return NULL;
      }
      //标识已经解析方法属性为true
      parsed_code_attribute = true;
      cfs->guarantee_more(8, CHECK_NULL);
      //最大栈
      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_NULL);
    // 校验字节码的长度大于0并且小于65535
    guarantee_property(code_length > 0 && code_length <= MAX_CODE_SIZE,"Invalid method Code length %u in class file %s",  code_length, CHECK_NULL);
}
   // 字节码指令的开始指针
      code_start = cfs->current();
      assert(code_start != NULL, "null code start");
      cfs->guarantee_more(code_length, CHECK_NULL);
      //字节码的文件流跳过字节码指令的长度
      cfs->skip_u1_fast(code_length);
      // 接下里解析异常表
      cfs->guarantee_more(2, CHECK_NULL);  
      // 获取2个字节的异常表的长度
      exception_table_length = cfs->get_u2_fast();
      // 解析异常表的开始位置
      if (exception_table_length > 0) {
        exception_table_start = parse_exception_table(cfs,  code_length,            exception_table_length,   CHECK_NULL);
}
 // 解析Code的附加属性
cfs->guarantee_more(2, CHECK_NULL); 
// 从文件流中获取2个字节的Code属性的个数
 u2 code_attributes_count = cfs->get_u2_fast();
  unsigned int calculated_attribute_length = 0;
//计算属性长度
  calculated_attribute_length =
   sizeof(max_stack) + sizeof(max_locals) + sizeof(code_length);
  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
     // 循环解析Code
      while (code_attributes_count--) {
        cfs->guarantee_more(6, CHECK_NULL);  // code_attribute_name_index, code_attribute_length
        const u2 code_attribute_name_index = cfs->get_u2_fast();
        const u4 code_attribute_length = cfs->get_u4_fast();
   calculated_attribute_length += code_attribute_length +                         sizeof(code_attribute_name_index) +
sizeof(code_attribute_length);
  //校验code属性名称索引     check_property(valid_symbol_at(code_attribute_name_index),"Invalid code attribute name index %u in class file %s", code_attribute_name_index,   CHECK_NULL);
    //校验code行表
    if (LoadLineNumberTables && cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_line_number_table()) {
   //解析行表
   parse_linenumber_table(code_attribute_length,
            code_length,
            &linenumber_table,
            CHECK_NULL);
    } else if (LoadLocalVariableTables &&cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_table()) {
  // 解析本地变量表
   if (!lvt_allocated) {
  //在thread的resouceArea分配空间
   localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2,  INITIAL_MAX_LVT_NUMBER);
   localvariable_table_start = NEW_RESOURCE_ARRAY_IN_THREAD(
   THREAD, const unsafe_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, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER);
   lvt_allocated = true;
}
// 如果大於最大本地變量表,則重新分配原先2倍空间
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(const unsafe_u2*, localvariable_table_start, lvt_cnt, max_lvt_cnt);
}
 //解析本地变量表并保存
 localvariable_table_start[lvt_cnt] =
            parse_localvariable_table(cfs,
           code_length,    max_locals, code_attribute_length,  &localvariable_table_length[lvt_cnt],
  false,  CHECK_NULL);
 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, const unsafe_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, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER);
            lvt_allocated = true;
          }
          //解析本地表类型
          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(const unsafe_u2*, localvariable_type_table_start, lvtt_cnt, max_lvtt_cnt);
          }
          // 解析本地变量表并保存
          localvariable_type_table_start[lvtt_cnt] =
            parse_localvariable_table(cfs,
                                      code_length,
                                      max_locals,
                                      code_attribute_length,
                                      &localvariable_type_table_length[lvtt_cnt],
              true,   CHECK_NULL);
          lvtt_cnt++;
        } else if (_major_version >= Verifier::STACKMAP_ATTRIBUTE_MAJOR_VERSION &&
  cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_stack_map_table()) {
  // 只有jdk1.6才有stackmap属性
  if (parsed_stackmap_attribute) {
            classfile_parse_error("Multiple StackMapTable attributes in class file %s", THREAD);
     return NULL;
 }
   // 解析stackmap的数据
    stackmap_data = parse_stackmap_table(cfs, code_attribute_length, _need_verify, CHECK_NULL);
   stackmap_data_length = code_attribute_length;
    parsed_stackmap_attribute = true;
 } else {
     // 跳过的位置属性
    cfs->skip_u1(code_attribute_length, CHECK_NULL);
        }
   }
      // 校验方法属性长度 
      if (_need_verify) {
 guarantee_property(method_attribute_length == calculated_attribute_length, "Code segment has wrong length in class file %s",
      CHECK_NULL);
   }
  } else if (method_attribute_name == vmSymbols::tag_exceptions()) {
      // 解析受检异常属性
      if (parsed_checked_exceptions_attribute) {
        classfile_parse_error("Multiple Exceptions attributes in class file %s",  THREAD);
        return NULL;
      }
      parsed_checked_exceptions_attribute = true;
      checked_exceptions_start =
            parse_checked_exceptions(cfs,
 &checked_exceptions_length, method_attribute_length,
   CHECK_NULL);
} else if (method_attribute_name == vmSymbols::tag_method_parameters()) {
      //解析方法参数
      if (method_parameters_seen) {
        classfile_parse_error("Multiple MethodParameters attributes in class file %s",  THREAD);
        return NULL;
      }
      method_parameters_seen = true;
      //从文件流中获取一个字节的参数长度
      method_parameters_length = cfs->get_u1_fast();
     // 计算方法参数长度
    const u2 real_length = (method_parameters_length * 4u) + 1u;
      if (method_attribute_length != real_length) {
        classfile_parse_error(
          "Invalid MethodParameters method attribute length %u in class file",
          method_attribute_length, THREAD);
        return NULL;
      }
    //文件流中方法参数数据的指针
  method_parameters_data = cfs->current();
  cfs->skip_u2_fast(method_parameters_length);
  cfs->skip_u2_fast(method_parameters_length);
      // 如果不支持反射,则忽略这个
      if (!vmClasses::Parameter_klass_loaded())
        method_parameters_length = -1;
    } else if (method_attribute_name == vmSymbols::tag_synthetic()) {
      //如果方法属性名称是Synthetic,
      if (method_attribute_length != 0) {
        classfile_parse_error(
          "Invalid Synthetic method attribute length %u in class file %s",
        method_attribute_length, THREAD);
        return NULL;
      }
      // 校验是否是编译器合成的方法
      access_flags.set_is_synthetic();
    } else if (method_attribute_name == vmSymbols::tag_deprecated()) {
      // 方法属性
      if (method_attribute_length != 0) {
        classfile_parse_error(
       "Invalid Deprecated method attribute length %u in class file %s",method_attribute_length, THREAD);
        return NULL;
      }
    } else if (_major_version >= JAVA_1_5_VERSION) {
     // 主版本号大于1.5
    if (method_attribute_name == vmSymbols::tag_signature()) { 
    // 泛型签名索引
    if (generic_signature_index != 0) {
      classfile_parse_error(
       "Multiple Signature attributes for method in class file %s",THREAD);
       return NULL;
  }
   // 方法属性长度
   if (method_attribute_length != 2) {
     classfile_parse_error(
      "Invalid Signature attribute length %u in class file %s",method_attribute_length, THREAD);
        return NULL;
    }
    // 泛型签名索引
    generic_signature_index = parse_generic_signature_attribute(cfs, CHECK_NULL);
      } else if (method_attribute_name == vmSymbols::tag_runtime_visible_annotations()) {
        if (runtime_visible_annotations != NULL) {
   classfile_parse_error(
     "Multiple RuntimeVisibleAnnotations attributes for method in class file %s",
            THREAD);
          return NULL;
        }
        // 运行时可见的注解
        runtime_visible_annotations_length = method_attribute_length;
        runtime_visible_annotations = cfs->current();
        assert(runtime_visible_annotations != NULL, "null visible annotations");
 cfs->guarantee_more(runtime_visible_annotations_length, CHECK_NULL);
 // 解析运行时可见的注解
parse_annotations(cp,
    runtime_visible_annotations,                     runtime_visible_annotations_length,
      &parsed_annotations,
     _loader_data,
 _can_access_vm_annotations);
        cfs->skip_u1_fast(runtime_visible_annotations_length);
      } else if (method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
      //运行时不可见注解
        if (runtime_invisible_annotations_exists) {
          classfile_parse_error(
            "Multiple RuntimeInvisibleAnnotations attributes for method in class file %s",
            THREAD);
          return NULL;
        }
        runtime_invisible_annotations_exists = true;
        if (PreserveAllAnnotations) {
          runtime_invisible_annotations_length = method_attribute_length;
          runtime_invisible_annotations = cfs->current();
          assert(runtime_invisible_annotations != NULL, "null invisible annotations");
        }
        cfs->skip_u1(method_attribute_length, CHECK_NULL);
      } else if (method_attribute_name == vmSymbols::tag_runtime_visible_parameter_annotations()) {
       // 解析运行时不可见的注解
        if (runtime_visible_parameter_annotations != NULL) {
          classfile_parse_error(
            "Multiple RuntimeVisibleParameterAnnotations attributes for method in class file %s",
            THREAD);
          return NULL;
   }
runtime_visible_parameter_annotations_length = method_attribute_length;
     // 运行时不可见的注解
     runtime_visible_parameter_annotations = cfs->current();
    cfs->skip_u1(runtime_visible_parameter_annotations_length, CHECK_NULL);
    } else if (method_attribute_name == vmSymbols::tag_runtime_invisible_parameter_annotations()) {
     if (runtime_invisible_parameter_annotations_exists) {
          classfile_parse_error(
            "Multiple RuntimeInvisibleParameterAnnotations attributes for method in class file %s",
            THREAD);
          return NULL;
        }
        runtime_invisible_parameter_annotations_exists = true;
        if (PreserveAllAnnotations) {
          runtime_invisible_parameter_annotations_length = method_attribute_length;
          runtime_invisible_parameter_annotations = cfs->current();
          assert(runtime_invisible_parameter_annotations != NULL,"null invisible parameter annotations");
      }
      cfs->skip_u1(method_attribute_length, CHECK_NULL);
  } else if (method_attribute_name == vmSymbols::tag_annotation_default()) {
   // 解析AnnotationDefault注解
     if (annotation_default != NULL) {
      classfile_parse_error(
       "Multiple AnnotationDefault attributes for method in class file %s", THREAD);
        return NULL;
     }
    annotation_default_length = method_attribute_length;
    annotation_default = cfs->current();
   assert(annotation_default != NULL, "null annotation default");
        cfs->skip_u1(annotation_default_length, CHECK_NULL);
      } 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",
            THREAD);
          return NULL;
     }
     runtime_visible_type_annotations_length = method_attribute_length;
        runtime_visible_type_annotations = cfs->current();
        assert(runtime_visible_type_annotations != NULL, "null visible type annotations");
        cfs->skip_u1(runtime_visible_type_annotations_length, CHECK_NULL);
      } 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",
            THREAD);
          return NULL;
        } else {
          runtime_invisible_type_annotations_exists = true;
        }
        if (PreserveAllAnnotations) {
          runtime_invisible_type_annotations_length = method_attribute_length;
          runtime_invisible_type_annotations = cfs->current();
          assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations");
        }
        cfs->skip_u1(method_attribute_length, CHECK_NULL);
      } else {
        // 跳过未知的属性
        cfs->skip_u1(method_attribute_length, CHECK_NULL);
      }
    } else {
      // 跳过未知的属性
      cfs->skip_u1(method_attribute_length, CHECK_NULL);
    }
  }

创建Method对象

  1. 创建InlineTableSizes对象记录一个Method对象的信息的大小,
  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);

6. 调用Method的allocate为Method对象.通过MetaspaceObj重载的new在metaSpace中分配内存资源。

Method* const m = Method::allocate(_loader_data,
                                     code_length,
                                     access_flags,
                                     &sizes,
                                     ConstMethod::NORMAL,
                             _cp->symbol_at(name_index),                                     CHECK_NULL);

7. 调用ConstMethod的allocate方法分配对象空间,同样也是通过MetaspaceObj重载的new在metaSpace中分配内存资源。

Method* Method::allocate(ClassLoaderData* loader_data,
                         int byte_code_size,
                         AccessFlags access_flags,
                         InlineTableSizes* sizes,
                         ConstMethod::MethodType method_type,
                         Symbol* name,
                         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, MetaspaceObj::MethodType, THREAD) Method(cm, access_flags, name);
}

8. 设置Method的对象的字段信息。

  ClassLoadingService::add_class_method_size(m->size()*wordSize);
  // 设置Method的字段信息
  m->set_constants(_cp);
  m->set_name_index(name_index);
  m->set_signature_index(signature_index);
  m->compute_from_signature(cp->symbol_at(signature_index));
  assert(args_size < 0 || args_size == m->size_of_parameters(), "");

  //设置code的属性:最大站 和 最大本地变量值
  m->set_max_stack(max_stack);
  m->set_max_locals(max_locals);
  if (stackmap_data != NULL) {
   m->constMethod()->copy_stackmap_data(_loader_data,
                                         (u1*)stackmap_data,
                                         stackmap_data_length,
                                         CHECK_NULL);
  }
  //设置字节码的文件流的方法的字节码指令的开始位置的指针
  m->set_code((u1*)code_start);

9.

  // 拷贝代码行表
  if (linenumber_table != NULL) {
    memcpy(m->compressed_linenumber_table(),
           linenumber_table->buffer(),
           linenumber_table_length);
  }
  //拷贝异常表
  if (exception_table_length > 0) {
    Copy::conjoint_swap_if_needed<Endian::JAVA>(exception_table_start,  m->exception_table_start(),
                     exception_table_length * sizeof(ExceptionTableElement),  sizeof(u2));
  }
  // 拷贝方法参数
  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((address)method_parameters_data);
      method_parameters_data += 2;
      elem[i].flags = Bytes::get_Java_u2((address)method_parameters_data);
      method_parameters_data += 2;
    }
  }
  // 拷贝受检异常表
  if (checked_exceptions_length > 0) {
    Copy::conjoint_swap_if_needed<Endian::JAVA>(checked_exceptions_start,m->checked_exceptions_start(),
 checked_exceptions_length * sizeof(CheckedExceptionElement),
  sizeof(u2));
  }
  // 拷贝本地变量表到ConstMethod
  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(methodHandle(THREAD, m));
  //设置隐藏类标志
  if (is_hidden()) {
    m->set_hidden(true);
  }
  // 拷贝方法注解到ConstMethod
  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);
  // 判断类的方法是finalize
  if (InstanceKlass::is_finalization_enabled() &&
      name == vmSymbols::finalize_method_name() &&
      signature == vmSymbols::void_method_signature()) {
    if (m->is_empty_method()) {
      _has_empty_finalizer = true;
    } else {
      _has_finalizer = true;
    }
  }
  // 判斷方法是 init 方法
  if (name == vmSymbols::object_initializer_name() &&
      signature == vmSymbols::void_method_signature() &&
      m->is_vanilla_constructor()) {
    _has_vanilla_constructor = true;
  }
  return m;

总结
本文主要分析JVM对class文件方法的字节码解析,主要涉及方法的名称、签名、字节码指令以及注解属性的解析, 并利用C++操作符对new的重载实现再metaspace分配空间资源,创建Method和ConstMethod对象。