Eclipseで作成した実行可能Jarの違い
Eclipseで実行可能なJarファイルを作成できるのですが、作成可能な3つのタイプに違いがある事が分かりましたので、まとめていきたいと思います。 「なぜ」というところまでは分かっていないのですが、DocuShareというアプリケーションを使ったシステム開発を行った際にたどり着いた結果です。
SceneBuilderのインストール
「Eclipse上で実行できるのに、配布したら動かない!!なぜだー!」という感じで、次のエラーが出力され調査を開始しました。
com.xerox.docushare.DSException: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.net.MalformedURLException: unknown protocol: rsrc; nested exception is:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.net.MalformedURLException: unknown protocol: rsrc; nested exception is:
com.xerox.docushare.DSException: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.net.MalformedURLException: unknown protocol: rsrc; nested exception is:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.net.MalformedURLException: unknown protocol: rsrc
at com.xerox.docushare.impl.DSFactorySpiImpl.createServer(DSFactorySpiImpl.java:70)
at com.xerox.docushare.DSFactory.createServer(DSFactory.java:68)
at jp.co.tenryu_aero.hoge.QualityRecordEcm.docushareConnect(QualityRecordEcm.java:89)
at jp.co.tenryu_aero.hoge.hoge.main(hoge.java:49) [rsrc:./:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58) [hoge.jar:na]
結論から行くと、JarRsrcLoaderから実行されると動かないという事が分かったのですが、実行可能Jarの作り方によって、MANIFEST.MFファイルに書かれるMain-Classが違ってきます。 Eclipseで、実行可能Jarを作成するには次の3つの方法が用意されています。
- 生成されるJARに必須ライブラリーを抽出
- 生成されるJARに必須ライブラリーをパッケージ
- 生成されるJARの隣のサブフォルダーに必須ライブラリーをコピー
それでは、3つある実行可能Jarのエクスポートを確認していきます。 最初に、エクスポートするプロジェクトのディレクトリ構造は次の物とします。
HelloWorld
|- Src
|- Hello.java
|- lib
|- dsapi.jar
|- jdom-1.1.3.jar
生成されるJARに必須ライブラリーを抽出
「生成されるJARに必須ライブラリーを抽出」を選択して実行可能Jarを作成するとJarファイルの中は次の構造となります。
Hello.jar
|- com
|- xerox
|- docushare
|- ...
|- META-INF
|- MANIFEST.MF
|- info.xml
|- org
|- jdom
|- adapters
|- AbstractDOMAdapter.class
|- ...
|- Hello.class
MANIFEST.MFの中は次のような構成。
Manifest-Version: 1.0
Class-Path: .
Main-Class: Hello
Name: org/jdom/
Specification-Title: JDOM Classes
Implementation-Title: org.jdom
Implementation-Version: 1.1.3
Specification-Version: 1.0
Specification-Vendor: jdom.org
Implementation-Vendor: jdom.org
Name: org/jdom/xpath/
...
生成されるJARに必須ライブラリーをパッケージ
「生成されるJARに必須ライブラリーをパッケージ」を選択して実行可能Jarを作成するとJarファイルの中は次の構造となります。
Hello.jar
|- META-INF
|- MANIFEST.MF
|- org
|- eclipse
|- jdt
|- internal
|- jarinjarloader
|- JarRsrcLoader.class
|- ...
|- Hello.class
|- dsapi.jar
|- jdom-1.1.3.jar
MANIFEST.MFの中は次のような構成。
Manifest-Version: 1.0
Rsrc-Class-Path: ./ dsapi.jar jdom-1.1.3.jar
Class-Path: .
Rsrc-Main-Class: Hello
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
ここでポイントとなるのがMain-ClassがJarRsrcLoaderになっている部分です。
生成されるJARの隣のサブフォルダーに必須ライブラリーをコピー
「生成されるJARの隣のサブフォルダーに必須ライブラリーをコピー」を選択して実行可能Jarを作成するとJarファイルの中は次の構造となります。
Hello.jar
|- META-INF
|- MANIFEST.MF
|- Hello.class
必須ライブラリーは、Hello_libというフォルダーが作成されサブフォルダーに配置されます。
Hello.jar
Hello_lib
|- dsapi,jar
|- jdom-1.1.3.jar
MANIFEST.MFの中は次のような構成。
Manifest-Version: 1.0
Class-Path: . Hello_lib/dsapi.jar Hello_lib/jdom-1.1.3.jar
Main-Class: Hello
まとめ
必須ライブラリをJarファイルに含める場合、Main-ClassがJarRsrcLoaderになり動作が変わる。