jdk/src/share/classes/java/lang/ClassLoader.java
このメソッドでは, 最初の呼び出し時にのみクラスローダの取得を行い, 二回目以降は初回の結果を使い回している (sclSet フィールドで呼び出し済みかどうかが確認できる. 取得されたクラスローダは scl フィールドにキャッシュされている)
private static synchronized void initSystemClassLoader() {
{- -------------------------------------------
(1) 既に一度呼び出されたことがあれば, 何もしない.
---------------------------------------- -}
if (!sclSet) {
{- -------------------------------------------
(1) まだ scl フィールドはセットされていないはず. もしセットされていたら IllegalStateException.
---------------------------------------- -}
if (scl != null)
throw new IllegalStateException("recursive invocation");
{- -------------------------------------------
(1) まず, sun.misc.Launcher.getLauncher() で取得した Launcher の getClassLoader() メソッドを呼び出し,
デフォルトのシステムクラスローダ(sun.misc.Launcher$AppClassLoader)を取得する.
次に, SystemClassLoaderAction オブジェクトを作成して
その run() メソッドを呼び出し,
ユーザが "java.system.class.loader" システムプロパティに設定したクラスローダを
(上記システムクラスローダを使って) 取得する.
"java.system.class.loader" が空の場合は, そのままデフォルトのシステムクラスローダが使用される.
(なお, SystemClassLoaderAction.run() の処理で PrivilegedActionException 例外が生じた場合は,
対応する例外を再スローして, このメソッドを抜ける)
---------------------------------------- -}
sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
if (l != null) {
Throwable oops = null;
scl = l.getClassLoader();
try {
scl = AccessController.doPrivileged(
new SystemClassLoaderAction(scl));
} catch (PrivilegedActionException pae) {
oops = pae.getCause();
if (oops instanceof InvocationTargetException) {
oops = oops.getCause();
}
}
if (oops != null) {
if (oops instanceof Error) {
throw (Error) oops;
} else {
// wrap the exception
throw new Error(oops);
}
}
}
{- -------------------------------------------
(1) すでに呼び出し済みだと印を付けておく.
---------------------------------------- -}
sclSet = true;
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.