openjdk17 hotspot JVM解析class文件

饭宝  金牌会员 | 2024-10-28 07:51:50 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 712|帖子 712|积分 2136

##openjdk17 hotspot JVM解析class文件
ClassFileParser::parse_stream 解析字节码
  1. void ClassFileParser::parse_stream(const ClassFileStream* const stream,
  2.                                    TRAPS) {
  3.   assert(stream != NULL, "invariant");
  4.   assert(_class_name != NULL, "invariant");
  5.   // BEGIN STREAM PARSING
  6.   stream->guarantee_more(8, CHECK);  // magic, major, minor
  7.   // Magic value
  8.   const u4 magic = stream->get_u4_fast();
  9.   guarantee_property(magic == JAVA_CLASSFILE_MAGIC,
  10.                      "Incompatible magic value %u in class file %s",
  11.                      magic, CHECK);
  12.   // Version numbers
  13.   _minor_version = stream->get_u2_fast();
  14.   _major_version = stream->get_u2_fast();
  15.   // Check version numbers - we check this even with verifier off
  16.   verify_class_version(_major_version, _minor_version, _class_name, CHECK);
  17.   stream->guarantee_more(3, CHECK); // length, first cp tag
  18.   u2 cp_size = stream->get_u2_fast();
  19.   guarantee_property(
  20.     cp_size >= 1, "Illegal constant pool size %u in class file %s",
  21.     cp_size, CHECK);
  22.   _orig_cp_size = cp_size;
  23.   if (is_hidden()) { // Add a slot for hidden class name.
  24.     cp_size++;
  25.   }
  26.   _cp = ConstantPool::allocate(_loader_data,
  27.                                cp_size,
  28.                                CHECK);
  29.   ConstantPool* const cp = _cp;
  30.   parse_constant_pool(stream, cp, _orig_cp_size, CHECK);
  31.   assert(cp_size == (const u2)cp->length(), "invariant");
  32.   // ACCESS FLAGS
  33.   stream->guarantee_more(8, CHECK);  // flags, this_class, super_class, infs_len
  34.   // Access flags
  35.   jint flags;
  36.   // JVM_ACC_MODULE is defined in JDK-9 and later.
  37.   if (_major_version >= JAVA_9_VERSION) {
  38.     flags = stream->get_u2_fast() & (JVM_RECOGNIZED_CLASS_MODIFIERS | JVM_ACC_MODULE);
  39.   } else {
  40.     flags = stream->get_u2_fast() & JVM_RECOGNIZED_CLASS_MODIFIERS;
  41.   }
  42.   if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION) {
  43.     // Set abstract bit for old class files for backward compatibility
  44.     flags |= JVM_ACC_ABSTRACT;
  45.   }
  46.   verify_legal_class_modifiers(flags, CHECK);
  47.   short bad_constant = class_bad_constant_seen();
  48.   if (bad_constant != 0) {
  49.     // Do not throw CFE until after the access_flags are checked because if
  50.     // ACC_MODULE is set in the access flags, then NCDFE must be thrown, not CFE.
  51.     classfile_parse_error("Unknown constant tag %u in class file %s", bad_constant, THREAD);
  52.     return;
  53.   }
  54.   _access_flags.set_flags(flags);
  55.   // This class and superclass
  56.   _this_class_index = stream->get_u2_fast();
  57.   check_property(
  58.     valid_cp_range(_this_class_index, cp_size) &&
  59.       cp->tag_at(_this_class_index).is_unresolved_klass(),
  60.     "Invalid this class index %u in constant pool in class file %s",
  61.     _this_class_index, CHECK);
  62.   Symbol* const class_name_in_cp = cp->klass_name_at(_this_class_index);
  63.   assert(class_name_in_cp != NULL, "class_name can't be null");
  64.   // Don't need to check whether this class name is legal or not.
  65.   // It has been checked when constant pool is parsed.
  66.   // However, make sure it is not an array type.
  67.   if (_need_verify) {
  68.     guarantee_property(class_name_in_cp->char_at(0) != JVM_SIGNATURE_ARRAY,
  69.                        "Bad class name in class file %s",
  70.                        CHECK);
  71.   }
  72. #ifdef ASSERT
  73.   // Basic sanity checks
  74.   if (_is_hidden) {
  75.     assert(_class_name != vmSymbols::unknown_class_name(), "hidden classes should have a special name");
  76.   }
  77. #endif
  78.   // Update the _class_name as needed depending on whether this is a named, un-named, or hidden class.
  79.   if (_is_hidden) {
  80.     assert(_class_name != NULL, "Unexpected null _class_name");
  81. #ifdef ASSERT
  82.     if (_need_verify) {
  83.       verify_legal_class_name(_class_name, CHECK);
  84.     }
  85. #endif
  86.   } else {
  87.     // Check if name in class file matches given name
  88.     if (_class_name != class_name_in_cp) {
  89.       if (_class_name != vmSymbols::unknown_class_name()) {
  90.         ResourceMark rm(THREAD);
  91.         Exceptions::fthrow(THREAD_AND_LOCATION,
  92.                            vmSymbols::java_lang_NoClassDefFoundError(),
  93.                            "%s (wrong name: %s)",
  94.                            class_name_in_cp->as_C_string(),
  95.                            _class_name->as_C_string()
  96.                            );
  97.         return;
  98.       } else {
  99.         // The class name was not known by the caller so we set it from
  100.         // the value in the CP.
  101.         update_class_name(class_name_in_cp);
  102.       }
  103.       // else nothing to do: the expected class name matches what is in the CP
  104.     }
  105.   }
  106.   // Verification prevents us from creating names with dots in them, this
  107.   // asserts that that's the case.
  108.   assert(is_internal_format(_class_name), "external class name format used internally");
  109.   if (!is_internal()) {
  110.     LogTarget(Debug, class, preorder) lt;
  111.     if (lt.is_enabled()){
  112.       ResourceMark rm(THREAD);
  113.       LogStream ls(lt);
  114.       ls.print("%s", _class_name->as_klass_external_name());
  115.       if (stream->source() != NULL) {
  116.         ls.print(" source: %s", stream->source());
  117.       }
  118.       ls.cr();
  119.     }
  120.   }
  121.   // SUPERKLASS
  122.   _super_class_index = stream->get_u2_fast();
  123.   _super_klass = parse_super_class(cp,
  124.                                    _super_class_index,
  125.                                    _need_verify,
  126.                                    CHECK);
  127.   // Interfaces
  128.   _itfs_len = stream->get_u2_fast();
  129.   parse_interfaces(stream,
  130.                    _itfs_len,
  131.                    cp,
  132.                    &_has_nonstatic_concrete_methods,
  133.                    CHECK);
  134.   assert(_local_interfaces != NULL, "invariant");
  135.   // Fields (offsets are filled in later)
  136.   _fac = new FieldAllocationCount();
  137.   parse_fields(stream,
  138.                _access_flags.is_interface(),
  139.                _fac,
  140.                cp,
  141.                cp_size,
  142.                &_java_fields_count,
  143.                CHECK);
  144.   assert(_fields != NULL, "invariant");
  145.   // Methods
  146.   AccessFlags promoted_flags;
  147.   parse_methods(stream,
  148.                 _access_flags.is_interface(),
  149.                 &promoted_flags,
  150.                 &_has_final_method,
  151.                 &_declares_nonstatic_concrete_methods,
  152.                 CHECK);
  153.   assert(_methods != NULL, "invariant");
  154.   // promote flags from parse_methods() to the klass' flags
  155.   _access_flags.add_promoted_flags(promoted_flags.as_int());
  156.   if (_declares_nonstatic_concrete_methods) {
  157.     _has_nonstatic_concrete_methods = true;
  158.   }
  159.   // Additional attributes/annotations
  160.   _parsed_annotations = new ClassAnnotationCollector();
  161.   parse_classfile_attributes(stream, cp, _parsed_annotations, CHECK);
  162.   assert(_inner_classes != NULL, "invariant");
  163.   // Finalize the Annotations metadata object,
  164.   // now that all annotation arrays have been created.
  165.   create_combined_annotations(CHECK);
  166.   // Make sure this is the end of class file stream
  167.   guarantee_property(stream->at_eos(),
  168.                      "Extra bytes at the end of class file %s",
  169.                      CHECK);
  170.   // all bytes in stream read and parsed
  171. }
复制代码
##解析方法
parse_methods(stream,
                _access_flags.is_interface(),
                &promoted_flags,
                &_has_final_method,
                &_declares_nonstatic_concrete_methods,
                CHECK);
  1. void ClassFileParser::parse_methods(const ClassFileStream* const cfs,
  2.                                     bool is_interface,
  3.                                     AccessFlags* promoted_flags,
  4.                                     bool* has_final_method,
  5.                                     bool* declares_nonstatic_concrete_methods,
  6.                                     TRAPS) {
  7.   assert(cfs != NULL, "invariant");
  8.   assert(promoted_flags != NULL, "invariant");
  9.   assert(has_final_method != NULL, "invariant");
  10.   assert(declares_nonstatic_concrete_methods != NULL, "invariant");
  11.   assert(NULL == _methods, "invariant");
  12.   cfs->guarantee_more(2, CHECK);  // length
  13.   const u2 length = cfs->get_u2_fast();
  14.   if (length == 0) {
  15.     _methods = Universe::the_empty_method_array();
  16.   } else {
  17.     _methods = MetadataFactory::new_array<Method*>(_loader_data,
  18.                                                    length,
  19.                                                    NULL,
  20.                                                    CHECK);
  21.     for (int index = 0; index < length; index++) {
  22.       Method* method = parse_method(cfs,
  23.                                     is_interface,
  24.                                     _cp,
  25.                                     promoted_flags,
  26.                                     CHECK);
  27.       if (method->is_final()) {
  28.         *has_final_method = true;
  29.       }
  30.       // declares_nonstatic_concrete_methods: declares concrete instance methods, any access flags
  31.       // used for interface initialization, and default method inheritance analysis
  32.       if (is_interface && !(*declares_nonstatic_concrete_methods)
  33.         && !method->is_abstract() && !method->is_static()) {
  34.         *declares_nonstatic_concrete_methods = true;
  35.       }
  36.       _methods->at_put(index, method);
  37.     }
  38.     if (_need_verify && length > 1) {
  39.       // Check duplicated methods
  40.       ResourceMark rm(THREAD);
  41.       NameSigHash** names_and_sigs = NEW_RESOURCE_ARRAY_IN_THREAD(
  42.         THREAD, NameSigHash*, HASH_ROW_SIZE);
  43.       initialize_hashtable(names_and_sigs);
  44.       bool dup = false;
  45.       const Symbol* name = NULL;
  46.       const Symbol* sig = NULL;
  47.       {
  48.         debug_only(NoSafepointVerifier nsv;)
  49.         for (int i = 0; i < length; i++) {
  50.           const Method* const m = _methods->at(i);
  51.           name = m->name();
  52.           sig = m->signature();
  53.           // If no duplicates, add name/signature in hashtable names_and_sigs.
  54.           if (!put_after_lookup(name, sig, names_and_sigs)) {
  55.             dup = true;
  56.             break;
  57.           }
  58.         }
  59.       }
  60.       if (dup) {
  61.         classfile_parse_error("Duplicate method name "%s" with signature "%s" in class file %s",
  62.                                name->as_C_string(), sig->as_klass_external_name(), THREAD);
  63.       }
  64.     }
  65.   }
  66. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

饭宝

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表