Top


定義場所(file name)

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

名前(function name)

typeArrayHandle ClassFileParser::parse_exception_table(u4 code_length,
                                                       u4 exception_table_length,
                                                       constantPoolHandle cp,
                                                       TRAPS) {

本体部(body)

  {- -------------------------------------------
  (1) (備考:
       例外ハンドラテーブルの情報は, クラスファイル中では
       Code アトリビュートの exception_table_length 及び exception_table に格納されている.

       クラスファイル中では, 以下のような tuple の配列として表される.
       * start_pc, end_pc : 例外ハンドリングの対象範囲
       * handler_pc : 対応するハンドラコードのアドレス(バイトコード上でのアドレス)
       * catch_type : キャッチ対象の例外のクラス名(を指し示す constant pool index))
      ---------------------------------------- -}

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

      ClassFileStream* cfs = stream();
      typeArrayHandle nullHandle;

  {- -------------------------------------------
  (1) パース結果を入れるための配列を生成する.
      (内部的には, 4個の int 値からなる tuple の配列として管理している.
       つまり, クラスファイルの内容をそのまま移しただけの素直な構造)
      ---------------------------------------- -}

      // 4-tuples of ints [start_pc, end_pc, handler_pc, catch_type index]
      typeArrayOop eh = oopFactory::new_permanent_intArray(exception_table_length*4, CHECK_(nullHandle));
      typeArrayHandle exception_handlers = typeArrayHandle(THREAD, eh);

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

      int index = 0;

  {- -------------------------------------------
  (1) まず, クラスファイルに (8 * exception_table_length) 分の長さが残っていることをチェック. 
      なければ ClassFormatError.
      ---------------------------------------- -}

      cfs->guarantee_more(8 * exception_table_length, CHECK_(nullHandle)); // start_pc, end_pc, handler_pc, catch_type_index

  {- -------------------------------------------
  (1) (以下の for ループで, exception_table_length 分だけの情報を読み込んで, 配列に詰めていく)
      ---------------------------------------- -}

      for (unsigned int i = 0; i < exception_table_length; i++) {

    {- -------------------------------------------
  (1.1) 例外ハンドラ情報を 1要素分だけ取得.
        ---------------------------------------- -}

        u2 start_pc = cfs->get_u2_fast();
        u2 end_pc = cfs->get_u2_fast();
        u2 handler_pc = cfs->get_u2_fast();
        u2 catch_type_index = cfs->get_u2_fast();

    {- -------------------------------------------
  (1.1) (verify)
        ---------------------------------------- -}

        // Will check legal target after parsing code array in verifier.
        if (_need_verify) {
          guarantee_property((start_pc < end_pc) && (end_pc <= code_length),
                             "Illegal exception table range in class file %s", CHECK_(nullHandle));
          guarantee_property(handler_pc < code_length,
                             "Illegal exception table handler in class file %s", CHECK_(nullHandle));
          if (catch_type_index != 0) {
            guarantee_property(valid_cp_range(catch_type_index, cp->length()) &&
                               is_klass_reference(cp, catch_type_index),
                               "Catch type in exception table has bad constant type in class file %s", CHECK_(nullHandle));
          }
        }

    {- -------------------------------------------
  (1.1) 取得した結果を配列に詰める.
        ---------------------------------------- -}

        exception_handlers->int_at_put(index++, start_pc);
        exception_handlers->int_at_put(index++, end_pc);
        exception_handlers->int_at_put(index++, handler_pc);
        exception_handlers->int_at_put(index++, catch_type_index);
      }

  {- -------------------------------------------
  (1) 結果をリターン
      ---------------------------------------- -}

      return exception_handlers;
    }

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