日記帳

日記です。

libgcj システムクラスローダ拡張機能

クラスローダの拡張機能っていうのは,クラスを事前に共有ライブラリにコンパイルしておくと,そのクラスが必要になったときに自動的に共有ライブラリをロードしてその中のクラスを利用してくれるという機能です.

具体的には gnu.pkg.SomeClass クラスが必要になって,それが実行ファイルにリンクされていない場合に,以下のようなファイルを順番に探していきます.

  • lib-gnu-pkg-SomeClass.so
  • lib-gnu-pkg.so
  • lib-gnu.so

ファイルが見付かればロードしてみてクラスがあればそれを利用します.

libgcj のシステムクラスローダの拡張機能は以下のページに書かれています.

リンクしなくても自動でロードされるのでなかなか便利ですね♪

以下ちょっと実験.


実験環境は Linux + gcj 3.3.2 です.

import java.lang.reflect.Method;

public class GCJClassLoaderTest
{
	public static void main(String[] args)
	{
		try
		{
			Class cls = Class.forName("not.exist.ClassName");
			Object obj = cls.newInstance();
			Method method = cls.getMethod("notFoundMethod", null);
			method.invoke(obj, null);
		}
		catch (Exception e) { e.printStackTrace(); }
	}
}

コンパイルして strace で実行.

% gcj -o GCJClassLoaderTest --main=GCJClassLoaderTest GCJClassLoaderTest.java
% strace -o log.txt ./GCJClassLoaderTest
java.lang.ClassNotFoundException: not.exist.ClassName not found in [file:/usr/local/java/junit/junit.jar, file:/home/sawai/GNUstep/Library/Libraries/Java, file:/usr/GNUstep/Local/Library/Libraries/Java, file:/usr/GNUstep/System/Library/Libraries/Java/, file:./, core:/]
   at _ZN4java4lang11VMThrowable16fillInStackTraceEPNS0_9ThrowableE (/usr/lib/libgcj.so.4.0.0)
   at _ZN4java4lang9Throwable16fillInStackTraceEv (/usr/lib/libgcj.so.4.0.0)
   ...
   at main (Unknown Source)
   at __libc_start_main (/lib/i686/libc-2.3.3.so)
   at _start (Unknown Source)

not.exist.ClassName な存在しないので当然例外が出て終了します.それは置いておいて得られた log.txt を見てみます.

% grep open log.txt | grep "lib-.*.so"
open("/usr/GNUstep/System/Library/Libraries/lib-not-exist-ClassName.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/i686/lib-not-exist-ClassName.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/lib-not-exist-ClassName.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/lib-not-exist-ClassName.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/home/sawai/GNUstep/Library/Libraries/lib-not-exist-ClassName.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/GNUstep/Local/Library/Libraries/lib-not-exist-ClassName.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/GNUstep/System/Library/Libraries/lib-not-exist-ClassName.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/lib-not-exist-ClassName.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/lib-not-exist-ClassName.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/GNUstep/System/Library/Libraries/lib-not-exist.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/i686/lib-not-exist.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/lib-not-exist.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/lib-not-exist.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/home/sawai/GNUstep/Library/Libraries/lib-not-exist.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/GNUstep/Local/Library/Libraries/lib-not-exist.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/GNUstep/System/Library/Libraries/lib-not-exist.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/lib-not-exist.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/lib-not-exist.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/GNUstep/System/Library/Libraries/lib-not.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/i686/lib-not.so", O_RDONLY)  = -1 ENOENT (No such file or directory)
open("/lib/lib-not.so", O_RDONLY)       = -1 ENOENT (No such file or directory)
open("/usr/lib/lib-not.so", O_RDONLY)   = -1 ENOENT (No such file or directory)
open("/home/sawai/GNUstep/Library/Libraries/lib-not.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/GNUstep/Local/Library/Libraries/lib-not.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/GNUstep/System/Library/Libraries/lib-not.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/lib-not.so", O_RDONLY)       = -1 ENOENT (No such file or directory)
open("/usr/lib/lib-not.so", O_RDONLY)   = -1 ENOENT (No such file or directory)

クラスパスに指定されたディレクトリや /lib /usr/lib 等々からファイルを探しているようです.

libgcj はいろいろとがんばっているんですねぇ.その割には gcj 使われてない気がしますけど…