jdk/src/share/classes/java/lang/ClassLoader.java
private static boolean loadLibrary0(Class fromClass, final File file) {
{- -------------------------------------------
(1) もし指定されたファイルがなければ (あるいはアクセス権がなければ), ここでリターンする.
---------------------------------------- -}
boolean exists = AccessController.doPrivileged(
new PrivilegedAction<Object>() {
public Object run() {
return file.exists() ? Boolean.TRUE : null;
}})
!= null;
if (!exists) {
return false;
}
{- -------------------------------------------
(1) ファイル名を正規化しておく.
---------------------------------------- -}
String name;
try {
name = file.getCanonicalPath();
} catch (IOException e) {
return false;
}
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
ClassLoader loader =
(fromClass == null) ? null : fromClass.getClassLoader();
Vector<NativeLibrary> libs =
loader != null ? loader.nativeLibraries : systemNativeLibraries;
{- -------------------------------------------
(1) もし既に自分がロード済みのライブラリであれば, ここでリターン.
---------------------------------------- -}
synchronized (libs) {
int size = libs.size();
for (int i = 0; i < size; i++) {
NativeLibrary lib = libs.elementAt(i);
if (name.equals(lib.name)) {
return true;
}
}
{- -------------------------------------------
(1) もし他のクラスローダーによってロードされていれば, UnsatisfiedLinkError.
---------------------------------------- -}
synchronized (loadedLibraryNames) {
if (loadedLibraryNames.contains(name)) {
throw new UnsatisfiedLinkError
("Native Library " +
name +
" already loaded in another classloader");
}
{- -------------------------------------------
(1) nativeLibraryContext の中を調べ, 同じライブラリがロード中かどうかを確かめる.
もし同じライブラリがロード途中であれば, これ以上することはないのでここでリターン.
(ただし, 担当のクラスローダが同じかどうかだけは確認しておく.
もし違っていたら同じライブラリが異なるクラスローダからロードされそうになっているということなので
UnsatisfiedLinkError.)
(なお, これは JNI_OnLoad() の処理中にロードが発生し,
同じライブラリがロードされた場合に起こりうるケース.
Runtime.load() や Runtime.loadLibrary() は synchronized なので,
他のスレッドが同じライブラリをロード中, という状況はあり得ない.)
---------------------------------------- -}
/* If the library is being loaded (must be by the same thread,
* because Runtime.load and Runtime.loadLibrary are
* synchronous). The reason is can occur is that the JNI_OnLoad
* function can cause another loadLibrary invocation.
*
* Thus we can use a static stack to hold the list of libraries
* we are loading.
*
* If there is a pending load operation for the library, we
* immediately return success; otherwise, we raise
* UnsatisfiedLinkError.
*/
int n = nativeLibraryContext.size();
for (int i = 0; i < n; i++) {
NativeLibrary lib = nativeLibraryContext.elementAt(i);
if (name.equals(lib.name)) {
if (loader == lib.fromClass.getClassLoader()) {
return true;
} else {
throw new UnsatisfiedLinkError
("Native Library " +
name +
" is being loaded in another classloader");
}
}
}
{- -------------------------------------------
(1) 新しい NativeLibrary オブジェクトを作り, NativeLibrary.load() でライブラリのロード処理を行う.
(なお, ロード処理の前後で nativeLibraryContext を使って現在ロード中であることが分かるようにしている)
---------------------------------------- -}
NativeLibrary lib = new NativeLibrary(fromClass, name);
nativeLibraryContext.push(lib);
try {
lib.load(name);
} finally {
nativeLibraryContext.pop();
}
{- -------------------------------------------
(1) ロードが成功すれば, loadedLibraryNames と libs に結果を追加し, true をリターンする.
---------------------------------------- -}
if (lib.handle != 0) {
loadedLibraryNames.addElement(name);
libs.addElement(lib);
return true;
}
{- -------------------------------------------
(1) ロードが失敗していたら false をリターンする.
---------------------------------------- -}
return false;
}
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.