hotspot/src/share/vm/classfile/classFileParser.cpp
typeArrayHandle ClassFileParser::parse_exception_table(u4 code_length,
u4 exception_table_length,
constantPoolHandle cp,
TRAPS) {
{- -------------------------------------------
(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.