hotspot/src/share/vm/utilities/exceptions.cpp
// Creates an exception oop, calls the <init> method with the given signature.
// and returns a Handle
// Initializes the cause if cause non-null
Handle Exceptions::new_exception(Thread *thread, Symbol* h_name,
Symbol* signature,
JavaCallArguments *args,
Handle h_cause, Handle h_loader,
Handle h_protection_domain) {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(Universe::is_fully_initialized(),
"cannot be called during initialization");
assert(thread->is_Java_thread(), "can only be called by a Java thread");
assert(!thread->has_pending_exception(), "already has exception");
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
Handle h_exception;
{- -------------------------------------------
(1) 生成対象の例外クラスを SystemDictionary から取得.
---------------------------------------- -}
// Resolve exception klass
klassOop ik = SystemDictionary::resolve_or_fail(h_name, h_loader, h_protection_domain, true, thread);
instanceKlassHandle klass (thread, ik);
{- -------------------------------------------
(1) instanceKlass::allocate_instance_handle() で指定の例外オブジェクトを確保した後,
JavaCalls::call_special() 経由でコンストラクタ(<init> メソッド)を呼び出して初期化を行う.
(さらに, 引数の h_cause が空でなければ,
java.lang.Throwable.initCause() も呼び出して cause の設定も行っている)
(ただし, 既に例外が発生している場合(= has_pending_exception() が true の場合),
あるいは以上の処理の途中で例外が発生した場合については,
そこで処理を打ち切ってそれ以上の処理は行わない)
---------------------------------------- -}
if (!thread->has_pending_exception()) {
assert(klass.not_null(), "klass must exist");
// We are about to create an instance - so make sure that klass is initialized
klass->initialize(thread);
if (!thread->has_pending_exception()) {
// Allocate new exception
h_exception = klass->allocate_instance_handle(thread);
if (!thread->has_pending_exception()) {
JavaValue result(T_VOID);
args->set_receiver(h_exception);
// Call constructor
JavaCalls::call_special(&result, klass,
vmSymbols::object_initializer_name(),
signature,
args,
thread);
}
}
// Future: object initializer should take a cause argument
if (h_cause() != NULL) {
assert(h_cause->is_a(SystemDictionary::Throwable_klass()),
"exception cause is not a subclass of java/lang/Throwable");
JavaValue result1(T_OBJECT);
JavaCallArguments args1;
args1.set_receiver(h_exception);
args1.push_oop(h_cause);
JavaCalls::call_virtual(&result1, klass,
vmSymbols::initCause_name(),
vmSymbols::throwable_throwable_signature(),
&args1,
thread);
}
}
{- -------------------------------------------
(1) もし, 以上の生成&初期化処理で何か例外が発生していた場合, そちらの方を優先する.
(返値として, 生成&初期化処理で発生した例外の方を返すことにする)
---------------------------------------- -}
// Check if another exception was thrown in the process, if so rethrow that one
if (thread->has_pending_exception()) {
h_exception = Handle(thread, thread->pending_exception());
thread->clear_pending_exception();
}
{- -------------------------------------------
(1) 結果をリターン
---------------------------------------- -}
return h_exception;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.