饭宝 发表于 2024-10-28 07:51:50

openjdk17 hotspot JVM解析class文件

##openjdk17 hotspot JVM解析class文件
ClassFileParser::parse_stream 解析字节码
void ClassFileParser::parse_stream(const ClassFileStream* const stream,
                                 TRAPS) {

assert(stream != NULL, "invariant");
assert(_class_name != NULL, "invariant");

// BEGIN STREAM PARSING
stream->guarantee_more(8, CHECK);// magic, major, minor
// Magic value
const u4 magic = stream->get_u4_fast();
guarantee_property(magic == JAVA_CLASSFILE_MAGIC,
                     "Incompatible magic value %u in class file %s",
                     magic, CHECK);

// Version numbers
_minor_version = stream->get_u2_fast();
_major_version = stream->get_u2_fast();

// Check version numbers - we check this even with verifier off
verify_class_version(_major_version, _minor_version, _class_name, CHECK);

stream->guarantee_more(3, CHECK); // length, first cp tag
u2 cp_size = stream->get_u2_fast();

guarantee_property(
    cp_size >= 1, "Illegal constant pool size %u in class file %s",
    cp_size, CHECK);

_orig_cp_size = cp_size;
if (is_hidden()) { // Add a slot for hidden class name.
    cp_size++;
}

_cp = ConstantPool::allocate(_loader_data,
                               cp_size,
                               CHECK);

ConstantPool* const cp = _cp;

parse_constant_pool(stream, cp, _orig_cp_size, CHECK);

assert(cp_size == (const u2)cp->length(), "invariant");

// ACCESS FLAGS
stream->guarantee_more(8, CHECK);// flags, this_class, super_class, infs_len

// Access flags
jint flags;
// JVM_ACC_MODULE is defined in JDK-9 and later.
if (_major_version >= JAVA_9_VERSION) {
    flags = stream->get_u2_fast() & (JVM_RECOGNIZED_CLASS_MODIFIERS | JVM_ACC_MODULE);
} else {
    flags = stream->get_u2_fast() & JVM_RECOGNIZED_CLASS_MODIFIERS;
}

if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION) {
    // Set abstract bit for old class files for backward compatibility
    flags |= JVM_ACC_ABSTRACT;
}

verify_legal_class_modifiers(flags, CHECK);

short bad_constant = class_bad_constant_seen();
if (bad_constant != 0) {
    // Do not throw CFE until after the access_flags are checked because if
    // ACC_MODULE is set in the access flags, then NCDFE must be thrown, not CFE.
    classfile_parse_error("Unknown constant tag %u in class file %s", bad_constant, THREAD);
    return;
}

_access_flags.set_flags(flags);

// This class and superclass
_this_class_index = stream->get_u2_fast();
check_property(
    valid_cp_range(_this_class_index, cp_size) &&
      cp->tag_at(_this_class_index).is_unresolved_klass(),
    "Invalid this class index %u in constant pool in class file %s",
    _this_class_index, CHECK);

Symbol* const class_name_in_cp = cp->klass_name_at(_this_class_index);
assert(class_name_in_cp != NULL, "class_name can't be null");

// Don't need to check whether this class name is legal or not.
// It has been checked when constant pool is parsed.
// However, make sure it is not an array type.
if (_need_verify) {
    guarantee_property(class_name_in_cp->char_at(0) != JVM_SIGNATURE_ARRAY,
                     "Bad class name in class file %s",
                     CHECK);
}

#ifdef ASSERT
// Basic sanity checks
if (_is_hidden) {
    assert(_class_name != vmSymbols::unknown_class_name(), "hidden classes should have a special name");
}
#endif

// Update the _class_name as needed depending on whether this is a named, un-named, or hidden class.

if (_is_hidden) {
    assert(_class_name != NULL, "Unexpected null _class_name");
#ifdef ASSERT
    if (_need_verify) {
      verify_legal_class_name(_class_name, CHECK);
    }
#endif

} else {
    // Check if name in class file matches given name
    if (_class_name != class_name_in_cp) {
      if (_class_name != vmSymbols::unknown_class_name()) {
      ResourceMark rm(THREAD);
      Exceptions::fthrow(THREAD_AND_LOCATION,
                           vmSymbols::java_lang_NoClassDefFoundError(),
                           "%s (wrong name: %s)",
                           class_name_in_cp->as_C_string(),
                           _class_name->as_C_string()
                           );
      return;
      } else {
      // The class name was not known by the caller so we set it from
      // the value in the CP.
      update_class_name(class_name_in_cp);
      }
      // else nothing to do: the expected class name matches what is in the CP
    }
}

// Verification prevents us from creating names with dots in them, this
// asserts that that's the case.
assert(is_internal_format(_class_name), "external class name format used internally");

if (!is_internal()) {
    LogTarget(Debug, class, preorder) lt;
    if (lt.is_enabled()){
      ResourceMark rm(THREAD);
      LogStream ls(lt);
      ls.print("%s", _class_name->as_klass_external_name());
      if (stream->source() != NULL) {
      ls.print(" source: %s", stream->source());
      }
      ls.cr();
    }
}

// SUPERKLASS
_super_class_index = stream->get_u2_fast();
_super_klass = parse_super_class(cp,
                                 _super_class_index,
                                 _need_verify,
                                 CHECK);

// Interfaces
_itfs_len = stream->get_u2_fast();
parse_interfaces(stream,
                   _itfs_len,
                   cp,
                   &_has_nonstatic_concrete_methods,
                   CHECK);

assert(_local_interfaces != NULL, "invariant");

// Fields (offsets are filled in later)
_fac = new FieldAllocationCount();
parse_fields(stream,
               _access_flags.is_interface(),
               _fac,
               cp,
               cp_size,
               &_java_fields_count,
               CHECK);

assert(_fields != NULL, "invariant");

// Methods
AccessFlags promoted_flags;
parse_methods(stream,
                _access_flags.is_interface(),
                &promoted_flags,
                &_has_final_method,
                &_declares_nonstatic_concrete_methods,
                CHECK);

assert(_methods != NULL, "invariant");

// promote flags from parse_methods() to the klass' flags
_access_flags.add_promoted_flags(promoted_flags.as_int());

if (_declares_nonstatic_concrete_methods) {
    _has_nonstatic_concrete_methods = true;
}

// Additional attributes/annotations
_parsed_annotations = new ClassAnnotationCollector();
parse_classfile_attributes(stream, cp, _parsed_annotations, CHECK);

assert(_inner_classes != NULL, "invariant");

// Finalize the Annotations metadata object,
// now that all annotation arrays have been created.
create_combined_annotations(CHECK);

// Make sure this is the end of class file stream
guarantee_property(stream->at_eos(),
                     "Extra bytes at the end of class file %s",
                     CHECK);

// all bytes in stream read and parsed
} ##解析方法
parse_methods(stream,
                _access_flags.is_interface(),
                &promoted_flags,
                &_has_final_method,
                &_declares_nonstatic_concrete_methods,
                CHECK);
void ClassFileParser::parse_methods(const ClassFileStream* const cfs,
                                    bool is_interface,
                                    AccessFlags* promoted_flags,
                                    bool* has_final_method,
                                    bool* declares_nonstatic_concrete_methods,
                                    TRAPS) {
assert(cfs != NULL, "invariant");
assert(promoted_flags != NULL, "invariant");
assert(has_final_method != NULL, "invariant");
assert(declares_nonstatic_concrete_methods != NULL, "invariant");

assert(NULL == _methods, "invariant");

cfs->guarantee_more(2, CHECK);// length
const u2 length = cfs->get_u2_fast();
if (length == 0) {
    _methods = Universe::the_empty_method_array();
} else {
    _methods = MetadataFactory::new_array<Method*>(_loader_data,
                                                   length,
                                                   NULL,
                                                   CHECK);

    for (int index = 0; index < length; index++) {
      Method* method = parse_method(cfs,
                                    is_interface,
                                    _cp,
                                    promoted_flags,
                                    CHECK);

      if (method->is_final()) {
      *has_final_method = true;
      }
      // declares_nonstatic_concrete_methods: declares concrete instance methods, any access flags
      // used for interface initialization, and default method inheritance analysis
      if (is_interface && !(*declares_nonstatic_concrete_methods)
      && !method->is_abstract() && !method->is_static()) {
      *declares_nonstatic_concrete_methods = true;
      }
      _methods->at_put(index, method);
    }

    if (_need_verify && length > 1) {
      // Check duplicated methods
      ResourceMark rm(THREAD);
      NameSigHash** names_and_sigs = NEW_RESOURCE_ARRAY_IN_THREAD(
      THREAD, NameSigHash*, HASH_ROW_SIZE);
      initialize_hashtable(names_and_sigs);
      bool dup = false;
      const Symbol* name = NULL;
      const Symbol* sig = NULL;
      {
      debug_only(NoSafepointVerifier nsv;)
      for (int i = 0; i < length; i++) {
          const Method* const m = _methods->at(i);
          name = m->name();
          sig = m->signature();
          // If no duplicates, add name/signature in hashtable names_and_sigs.
          if (!put_after_lookup(name, sig, names_and_sigs)) {
            dup = true;
            break;
          }
      }
      }
      if (dup) {
      classfile_parse_error("Duplicate method name \"%s\" with signature \"%s\" in class file %s",
                               name->as_C_string(), sig->as_klass_external_name(), THREAD);
      }
    }
}
}

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: openjdk17 hotspot JVM解析class文件