2

私の Java プロジェクトでは、H2 インメモリ データベースを使用しています。このデータベースでは、アプリケーションを初期化するときに JDBC ドライバーをロードする必要があります。H2 .jar ファイルを動的にロードする必要があるため、次のようにします。

String classname = "org.h2.Driver";
URL u = new URL("jar:file:libs/h2.jar!/");
URLClassLoader ucl = new URLClassLoader(new URL[] { u });
Driver d = (Driver) Class.forName(classname, true, ucl).newInstance();
DriverManager.registerDriver(new DriverShim(d));

H2 .jar ファイルを Java ソース コード フォルダーの外側の「libs」フォルダー (つまり、Eclipse では、この「libs」ディレクトリは「src」フォルダーと同じレベルにあります) に入れると、このアプローチは正常に機能します。 . ただし、残念ながら、この H2 .jar ファイルをソース コード フォルダー ツリー内のメイン クラス フォルダーの下のフォルダーに配置する必要があります。

たとえば、私の Java パッケージ構造は Eclipse では次のようになります。

<project>/src/my/app/MyApp.java              // main class of my application
<project>/src/my/app/sub/package/h2.jar      // how to access this?
<project>/libs/h2.jar                        // loading from here works

これがばかげていることはわかっていますが、残念ながら、この奇妙な設定で作業する必要があります。しかし、私が知らないこと: このセットアップで作業するために、Java コード (上記にリストされている) を編集するにはどうすればよいでしょうか?

編集:これは Eclipse の外部でも機能する必要があるため、JAR ファイルを Eclipse の Java ビルド パスに追加することはできません。

EDIT2:「jar:file:my/app/sub/package/h2.jar!/」をロードしようとしましたが、うまくいきませんでした。

すべての役立つアイデアを前もってありがとう!

よろしく、 マティアス

4

1 に答える 1

2

classpath:一部のフレームワークでは、プレフィックスを使用して JAR 内のファイルを参照できます。URLClassLoader がネイティブでサポートしているとは思えませんが、試してみる価値はあります (例: classpath:/my/app/sub/package/h2.jar)。しかし、これは URLClassLoader では機能しないため、別の方法を次に示します。

これを行う 1 つの方法は、クラスパスから JAR ファイルを読み取り (getResourceAsStream を使用)、それを (ZipInputStream を使用して) メモリ (バイト配列のマップなど) に解凍し、そこからクラスをロードする独自の ClassLoader を作成することです。

もう 1 つの少し簡単な方法は、クラスパスから JAR ファイルを読み取り、それを一時ファイルに書き込むことです。次に、プレーンな URLClassLoader を使用して、そこからクラスをロードできます。これには、ファイルをファイルに書き込む必要があり、おそらく JVM が終了するまでファイルを削除できないという欠点があります ( Java 7以降を使用している場合を除く)。

外部プロセスを起動するために使用していますが、1 つのプロジェクトで2 番目のアプローチ (一時ファイルへのコピー)を使用しています。なぜそのような要件があるのか​​、お聞きしたいと思います。アプリケーション全体を 1 つの JAR に入れるだけの場合は、それを実現するためのより簡単な方法が多数あります (Maven Assembly Plugin、Maven Shade Plugin、Jar Jar Links、One-JAR など)。


いいえ、宿題ではありませんが、my/app/* の下のクラスと他のいくつかのクラス (私からではない) を使用して、ソリューション全体を自動的にビルドするオンライン ビルド システムです。とにかく、私はこのシステムの内部を知らないので、これ以上詳しく説明することはできません. 言ったように、私は単にそれと一緒に暮らす必要があり、それが私がここで尋ねている理由です...

あなたはWTF環境で作業しているように思えます (名前はありますか?)。そこで、ハッキングを開始する方法をいくつか紹介します。

環境、特にソース ファイルが保存されているディレクトリ、生成された .class ファイルが保存されているディレクトリ、およびプログラム実行時の現在の作業ディレクトリの絶対ファイル パスについて詳しく調べてください。

実行時にプログラムが出力する出力を取得できる場合は、File.listFiles()を使用してマシンのディレクトリ ツリーをクロールするデバッグ コードをアプリケーションに追加できます。コンパイル時に発生することからのみ出力を取得できる場合は、独自の注釈プロセッサを作成することにより、コンパイル中に独自のコードを実行できる可能性があります(Java 6 以降、apt は javac の一部です)。最初に個別にコンパイルする必要があります。

作業ディレクトリはシステム プロパティから読み取ることができuser.dir、クラス ファイルの場所はおそらくjava.class.pathシステム プロパティから取得できます (カスタム クラス ローダーが使用されていない場合)。ソース ディレクトリ内の JAR ファイルがクラスパスにコピーされるという保証はないので、いろいろ調べてみる必要があるかもしれません。

次に、JAR ファイルのファイル パスがわかれば、その URL を取得しnew File("path/to/h2.jar").toURI().toURL()て URLClassLoader に渡すことができます。

他に何も機能しない場合は、ライブラリのソース コードをアップロードし、プロジェクトと共にコンパイルします。

長期的には、WTF ビルド環境を、標準のビルド ツール (Maven など) と一般的な CI サーバー (Jenkins など) を使用する環境に置き換えるようにしてください。プロジェクトに多くのライブラリ依存関係があるのは普通のことなので、それらを使用するためにビルド環境をハックする必要はありません。

于 2012-05-10T21:07:24.030 に答える