Top


定義場所(file name)

hotspot/src/share/vm/classfile/classFileParser.cpp

説明(description)

この関数では attributes 個数分のループで読み込み&確認処理をする.

なお, 結果は (返り値ではなく) 引数で渡されたポインタに書き込まれて返される. それぞれの引数に書き込まれる値は以下の通り.

ConstantValue attribute があった場合, それが指す CP の index が書き込まれる

Synthetic attribute があった場合, true が書き込まれる

Signature attribute があった場合, それが指す CP の index が書き込まれる

RunTimeVisible(およびInvisible)Annotation があった場合, それら全てを ClassFileParser::assemble_annotations() でまとめた typeArrayHandle へのポインタが書き込まれる (#TODO)(どんな Annotation がつく?)

// Parse attributes for a field.

名前(function name)

void ClassFileParser::parse_field_attributes(constantPoolHandle cp,
                                             u2 attributes_count,
                                             bool is_static, u2 signature_index,
                                             u2* constantvalue_index_addr,
                                             bool* is_synthetic_addr,
                                             u2* generic_signature_index_addr,
                                             typeArrayHandle* field_annotations,
                                             TRAPS) {

本体部(body)

  {- -------------------------------------------
  (1) (変数宣言など)
      ---------------------------------------- -}

      ClassFileStream* cfs = stream();
      assert(attributes_count > 0, "length should be greater than 0");
      u2 constantvalue_index = 0;
      u2 generic_signature_index = 0;
      bool is_synthetic = false;
      u1* runtime_visible_annotations = NULL;
      int runtime_visible_annotations_length = 0;
      u1* runtime_invisible_annotations = NULL;
      int runtime_invisible_annotations_length = 0;

  {- -------------------------------------------
  (1) 引数で指定された attribute の個数分だけループ
      ---------------------------------------- -}

      while (attributes_count--) {

    {- -------------------------------------------
  (1.1) attribute_name_index と attribute_length を読み込む.
        attribute_name_index については, その index 値が Constant Pool 内に収まっており, 
        utf8_info を指していることを確認する.
        ---------------------------------------- -}

        cfs->guarantee_more(6, CHECK);  // attribute_name_index, attribute_length
        u2 attribute_name_index = cfs->get_u2_fast();
        u4 attribute_length = cfs->get_u4_fast();
        check_property(valid_cp_range(attribute_name_index, cp->length()) &&
                       cp->tag_at(attribute_name_index).is_utf8(),
                       "Invalid field attribute index %u in class file %s",
                       attribute_name_index,
                       CHECK);
        Symbol* attribute_name = cp->symbol_at(attribute_name_index);

    {- -------------------------------------------
  (1.1) 以下, 読み込んだ attribute_name に応じて, 適切に読み込み&内容の確認処理を行う.
        ---------------------------------------- -}

    {- -------------------------------------------
  (1.1) * ConstantValue attribute の場合は, static でないといけない
            (non-static な ConstantValue attribute は無視することになっている).
          また, 1つのフィールドに複数の ConstantValue attribute が指定されてはいけない.
            (局所変数 constantvalue_index は, 初期値はゼロで, 
             ConstantValue attribute が見つかればその constantvalue_index 値がセットされる.
             よって, これが 0 でなければ複数の ConstantValue attribute が指定されていることになる)
          また, attribute_length が 2 でないといけない.

          以上のチェックが終わったら, constantvalue_index を読み込み, 
          (_need_verify が立っていれば) ClassFileParser::verify_constantvalue() で
          フィールドの型と指示先の定数の型があっているかどうかをチェック.
        ---------------------------------------- -}

        if (is_static && attribute_name == vmSymbols::tag_constant_value()) {
          // ignore if non-static
          if (constantvalue_index != 0) {
            classfile_parse_error("Duplicate ConstantValue attribute in class file %s", CHECK);
          }
          check_property(
            attribute_length == 2,
            "Invalid ConstantValue field attribute length %u in class file %s",
            attribute_length, CHECK);
          constantvalue_index = cfs->get_u2(CHECK);
          if (_need_verify) {
            verify_constantvalue(constantvalue_index, signature_index, cp, CHECK);
          }

    {- -------------------------------------------
  (1.1) * Synthetic attribute の場合は, attribute_length が 0 でないといけない.
          (Synthetic attribute には他に情報は無いので単にこれだけ)

          以上のチェックが終わったら, is_synthetic を true にセットし, 
          呼び出し元に Synthetic があったことを通知できるようにしておく.
        ---------------------------------------- -}

        } else if (attribute_name == vmSymbols::tag_synthetic()) {
          if (attribute_length != 0) {
            classfile_parse_error(
              "Invalid Synthetic field attribute length %u in class file %s",
              attribute_length, CHECK);
          }
          is_synthetic = true;

    {- -------------------------------------------
  (1.1) * Deprecated attribute の場合は, attribute_length が 0 でないといけない.
          (Deprecated attribute には他に情報は無いので単にこれだけ)

          (Deprecated attribute については, 呼び出し元には何の情報も返されない)
        ---------------------------------------- -}

        } else if (attribute_name == vmSymbols::tag_deprecated()) { // 4276120
          if (attribute_length != 0) {
            classfile_parse_error(
              "Invalid Deprecated field attribute length %u in class file %s",
              attribute_length, CHECK);
          }

    {- -------------------------------------------
  (1.1) バージョンが Java 5 以降であれば, Java 5 で追加されたアノテーションの処理も行う. (#TODO)
        ---------------------------------------- -}

        } else if (_major_version >= JAVA_1_5_VERSION) {
          if (attribute_name == vmSymbols::tag_signature()) {
            if (attribute_length != 2) {
              classfile_parse_error(
                "Wrong size %u for field's Signature attribute in class file %s",
                attribute_length, CHECK);
            }
            generic_signature_index = cfs->get_u2(CHECK);
          } else if (attribute_name == vmSymbols::tag_runtime_visible_annotations()) {
            runtime_visible_annotations_length = attribute_length;
            runtime_visible_annotations = cfs->get_u1_buffer();
            assert(runtime_visible_annotations != NULL, "null visible annotations");
            cfs->skip_u1(runtime_visible_annotations_length, CHECK);
          } else if (PreserveAllAnnotations && attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
            runtime_invisible_annotations_length = 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);

    {- -------------------------------------------
  (1.1) もし認識できない attribute であれば, 単に読み飛ばすだけ.
        (なお 2つあるのは, _major_version >= JAVA_1_5_VERSION の場合とそうでない場合に対応. どちらにせよ読み飛ばすだけだけど)
        ---------------------------------------- -}

          } else {
            cfs->skip_u1(attribute_length, CHECK);  // Skip unknown attributes
          }
        } else {
          cfs->skip_u1(attribute_length, CHECK);  // Skip unknown attributes
        }
      }

  {- -------------------------------------------
  (1) 最後に, パース結果を引数で渡されたポインタに書き込んでリターン.
      ---------------------------------------- -}

      *constantvalue_index_addr = constantvalue_index;
      *is_synthetic_addr = is_synthetic;
      *generic_signature_index_addr = generic_signature_index;
      *field_annotations = assemble_annotations(runtime_visible_annotations,
                                                runtime_visible_annotations_length,
                                                runtime_invisible_annotations,
                                                runtime_invisible_annotations_length,
                                                CHECK);
      return;
    }

This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.