home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

Java/jarファイルの配布と実行方式

Java/jarファイルの配布と実行方式

Java / jarファイルの配布と実行方式
id: 1121 所有者: msakamoto-sf    作成日: 2012-11-04 17:37:03
カテゴリ: Java 

実行可能なJavaプログラムをjarファイルで配布する場合、その形態として次の2方式をよく見かけます。

  • "-jar ほげほげ.jar"で実行可能な単一jarファイルでの配布 : GUIのJavaアプリで時々見かけます。OSによってはjarファイルをダブルクリックするだけで実行できるので非常にお手軽です。
  • 依存jarと、それらをclasspathに自動的に追加して実行してくれる起動スクリプト(.bat, .sh)がzipやtar.gzで一緒に配布される : 依存jarが存在する、Tomcatなどサーバ系の配布でよく目にします。

本記事ではこれらの配布と実行方式の実現方法について調べてみました。



step1 : MANIFEST.MFを使って"-jar"で実行可能なjarファイルを作成する(依存jar無しの超シンプル版)

まずは一番シンプルな形態として、依存jarが無い状態で"-jar"で実行可能なjarファイルを作成してみます。

シンプルなJavaプロジェクト(.javaを手動でコンパイル、jarファイルも手動で作成)

Hello.java:

public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello");
    }
}

コンパイル&実行:

$ javac Hello.java
$ java Hello
Hello

単純にjarファイルを作成して実行してみます:

$ jar cf hello-nomf.jar -C hello .

$ jar tf hello-nomf.jar
META-INF/
META-INF/MANIFEST.MF
Hello.class
Hello.java

$ java -cp hello-nomf.jar Hello
Hello

このjarファイルを実行可能にするには、マニフェスト・ファイルの"Main-Class"属性にmain()を実行するクラス名を指定します。
以下のようなテキストファイルを用意します。最後の空行は必須です。
hello.mf:

Main-Class: Hello

jar作成&実行:

$ jar cmf hello.mf hello-mf.jar -C hello .
$ java -jar hello-mf.jar
Hello

正常に"-jar"だけで実行できました。展開して中身を確認してみます。

$ jar xf hello-mf.jar META-INF/MANIFEST.MF
$ cat META-INF/MANIFEST.MF
Manifest-Version: 1.0
Created-By: 1.7.0_07 (Oracle Corporation)
Main-Class: Hello

Mavenプロジェクトで"Main-Class"属性を指定してみる

MavenプロジェクトでMain-Class属性を指定してみます。

quickstartを使ってMavenプロジェクトを生成:

$ mvn archetype:generate -DarchetypeArtifactId=maven-archetype-quickstart
...
Define value for property 'groupId': : step1-mf-mvn
Define value for property 'artifactId': : step1-mf-mvn
Define value for property 'version':  1.0-SNAPSHOT: :
Define value for property 'package':  step1-mf-mvn: : step1
Confirm properties configuration:
groupId: step1-mf-mvn
artifactId: step1-mf-mvn
version: 1.0-SNAPSHOT
package: step1
...


$ cat ./src/main/java/step1/App.java
package step1;

/**
 * Hello world!
 *
 */
public class App
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
    }
}

Main-Class属性を指定するには、maven-jar-pluginの"<archive>" -> "<manifest>" -> "<mainClass>"に指定します。
pom.xml抜粋:

...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <mainClass>step1.App</mainClass>
            </manifest>
          </archive>
        </configuration>
      </plugin>
    </plugins>
  </build>
...

ビルド&実行:

$ mvn package

$ java -jar target/step1-mf-mvn-1.0-SNAPSHOT.jar
Hello World!

実際のMANIFEST.MFファイルの中身:

$ jar xf target/step1-mf-mvn-1.0-SNAPSHOT.jar META-INF/MANIFEST.MF
$ cat META-INF/MANIFEST.MF
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: FengJing
Build-Jdk: 1.7.0_07
Main-Class: step1.App

step2 : MANIFEST.MFを使って"-jar"で実行可能なjarファイルを作成する(依存jar有り版)

step1では依存jarが無い、一番シンプルな形で確認しました。step2では、依存jarが存在する、より現実的な場合での対応方法を試してみます。

マニフェスト・ファイルののClass-Path属性の基本

マニフェスト・ファイルでは、"Class-Path"属性を使ってjarファイルの配置場所からの相対パスでclasspathに通したいjarを指定することが可能です。

サンプル:

step2-with-jar/
  depjars-src/
    depjar1/Lib1.java, Lib1.class
    depjar2/Lib2.java, Lib2.class
  depjars-lib/
    depjar1.jar
    depjar2.jar
  Hello.java
  hello.mf

Hello.javaは以下の様な内容で、depjar1.jar中の"depjar1.Lib1"およびdepjar2.jar中の"depjar2.Lib2"に依存しています。

import depjar1.Lib1;
import depjar2.Lib2;
 
public class Hello {
    public static void main(String[] args) {
        int a = 5;
        int b = 3;
        System.out.println(Lib1.calc(a, b));
        System.out.println(Lib2.calc(a, b));
    }
}

コンパイル:

$ cd step2-with-jar/
$ javac -cp .:depjars-src Hello.java

マニフェスト・ファイルとして以下の内容を作成し、hello.mfとして保存し、jar作成時に指定します。
hello.mf:

Main-Class: Hello
Class-Path: ./depjars-lib/depjar1.jar ./depjars-lib/depjar2.jar

jarを作成し、実行します。Class-Path属性により、jarファイルからの相対パスで"depjars-lib"以下のjarファイルが参照され、正常に実行されました。

$ jar cmf hello.mf hello.jar Hello.class
$ jar tf hello.jar
META-INF/
META-INF/MANIFEST.MF
Hello.class
$ java -jar hello.jar
8
2

MavenでのClass-Path属性の指定と依存jarの集約

Mavenでもマニフェスト・ファイルのClass-Path属性を設定できます。"mainClass"を設定した時と同様、Maven Archiverの提供する"addClasspath"設定を使うことで、Maven側で依存しているjarを自動的にClass-Path属性にまとめてくれます。

step2-mvn1/pom.xml:

<project ...>
  ...
  <dependencies>
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.1.1</version>
    </dependency>
    <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>
      <version>2.6</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <mainClass>step2.App</mainClass>
              <!-- Class-Path属性の自動設定 -->
              <addClasspath>true</addClasspath>
              <!-- Class-Path属性で"lib/"などprefixを付けたい時に指定 -->
              <classpathPrefix>lib</classpathPrefix>
            </manifest>
          </archive>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

src/main/java/step2/App.java:

package step2;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.lang.WordUtils;
 
public class App
{
    static Log log = LogFactory.getLog(App.class);
    public static void main( String[] args )
    {
        log.fatal("fatal log sample");
        log.error("error log sample");
        log.warn("warn log sample");
        log.info("info log sample");
        log.debug("debug log sample");
        log.trace("trace log sample");
        System.out.println(WordUtils.swapCase("Hello World!"));
    }
}

パッケージングして、マニフェスト・ファイルを確認してみます。

$ mvn package
$ jar xf target/step2-mvn1-1.0-SNAPSHOT.jar META-INF/MANIFEST.MF
$ cat META-INF/MANIFEST.MF
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: FengJing
Build-Jdk: 1.7.0_07
Main-Class: step2.App
Class-Path: lib/commons-logging-1.1.1.jar lib/commons-lang-2.6.jar

commons-loggingとcommons-langの依存jarがClass-Path属性に指定されていることが確認されます。
しかし、この段階ではまだ"lib/"ディレクトリ自体がまだ存在しないので実行できいません。"lib/"ディレクトリを作成し、依存jarを集約するにはmaven-dependency-pluginのcopy-dependenciesゴールを使います。

$ mvn dependency:copy-dependencies -DoutputDirectory=target/lib -DincludeScope=compile
... "outputDirectory"で"target/lib"以下にコピー
... "includeScope"で"compile"スコープの依存jarのみをコピー

この時点で以下のようなjar構成になります。

step2-mvn1/target/
  step2-mvn1-1.0-SNAPSHOT.jar
  lib/
    commons-lang-2.6.jar
    commons-logging-1.1.1.jar

準備出来ましたので、実行してみます。

$ java -jar target/step2-mvn1-1.0-SNAPSHOT.jar
11 04, 2012 12:38:24 午後 step2.App main
SEVERE: fatal log sample
11 04, 2012 12:38:24 午後 step2.App main
SEVERE: error log sample
11 04, 2012 12:38:24 午後 step2.App main
WARNING: warn log sample
11 04, 2012 12:38:24 午後 step2.App main
情報: info log sample
hELLO wORLD!

うまく動作してくれました。

maven-assembly-pluginを使った依存jarのパッケージング

上で紹介した "dependency:copy-dependencies" はあくまでもmvnコマンドが実行できる開発環境に限定されます。実際に配布する場合はzipやtar.gzなどにパッケージングすることになり、Mavenの場合ではmaven-assembly-pluginを使って依存jarのパッケージングを自動化できます。

step2-mvn1のMavenプロジェクトを "step2-mvn2" にコピーして、pom.xmlを以下のようにします。
step2-mvn2/pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>step2-mvn2</groupId>
  <artifactId>step2-mvn2</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>step2-mvn2</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.1.1</version>
    </dependency>
    <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>
      <version>2.6</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <mainClass>step2.App</mainClass>
              <!-- Class-Path属性を指定します。 -->
              <addClasspath>true</addClasspath>
              <!--
                maven-assembly-pluginのデフォルトでは、
                artifactのjar自体も依存jarと同じディレクトリに
                まとめられますので、あえてclasspathPrefix
                は指定せず、アプリのjarと同じ場所に
                依存jarがあるものとします。
              -->
            </manifest>
          </archive>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.3</version>
        <configuration>
          <descriptors>
            <descriptor>src/assemble/bin.xml</descriptor>
          </descriptors>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

maven-assembly-pluginは配布用のパッケージの"assemble"に利用されます。設定が複雑になりがちなこともあり、詳細な設定を外部の"descriptor" XMLファイルに記載し、pom.xmlではdescriptor XMLファイルの場所だけを指定しています。

step2-mvn2/src/assemble/bin.xml:

<assembly>
  <id>bin</id>
  <formats>
    <!-- 今回は"<format>"としてtar.gz, tar.bz2, zipの3種類を指定します。 -->
    <format>tar.gz</format>
    <format>tar.bz2</format>
    <format>zip</format>
  </formats>
  <dependencySets>
    <dependencySet>
      <!-- artifact自身のjarを含め、依存jarをパッケージの直下に配置します。 -->
      <outputDirectory>/</outputDirectory>
      <includes>
        <!-- 集約する対象は依存する"jar"のみにします。 -->
        <include>*:jar</include>
      </includes>
    </dependencySet>
  </dependencySets>
</assembly>
$ mvn package
...
[INFO] Building tar: .../
[INFO] Building tar: .../target/step2-mvn2-1.0-SNAPSHOT-bin.tar.gz
[INFO] Building tar: .../target/step2-mvn2-1.0-SNAPSHOT-bin.tar.bz2
[INFO] Building zip: .../target/step2-mvn2-1.0-SNAPSHOT-bin.zip
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

試しにtar.gzを適当なディレクトリに展開してみます。

$ tar zxf step2-mvn2-1.0-SNAPSHOT-bin.tar.gz
$ find .
.
./step2-mvn2-1.0-SNAPSHOT
./step2-mvn2-1.0-SNAPSHOT/commons-lang-2.6.jar
./step2-mvn2-1.0-SNAPSHOT/commons-logging-1.1.1.jar
./step2-mvn2-1.0-SNAPSHOT/step2-mvn2-1.0-SNAPSHOT.jar
./step2-mvn2-1.0-SNAPSHOT-bin.tar.gz

実行してみます。

$ cd ./step2-mvn2-1.0-SNAPSHOT
$ java -jar step2-mvn2-1.0-SNAPSHOT.jar
11 04, 2012 2:37:04 午後 step2.App main
SEVERE: fatal log sample
11 04, 2012 2:37:04 午後 step2.App main
SEVERE: error log sample
11 04, 2012 2:37:04 午後 step2.App main
WARNING: warn log sample
11 04, 2012 2:37:04 午後 step2.App main
情報: info log sample
hELLO wORLD!

問題なく動作しています。これで、tarやzipなどで依存jarも含めて配布できるようになりました。

コーヒーブレイク:step1-2までの参考資料

step3 : batやshでjarファイルのリストを取り出しclasspathを調整する

ここまではjarファイルの機能だけで実行可能にしたり依存jarの問題を対応してきました。このstep3では、Tomcatの配布パッケージで見られるようにbatやshファイルで依存関係を解決するアプローチを紹介します。

以前、Apache MINAを使ったechoサーバの実験でcodereposに"echo_samples/act9"というサンプルコードをupし、その中でこのアプローチを採用し、batやshで依存jarの一覧を取り出してclasspathに指定していますので、そちらを簡単に紹介していきます。

http://coderepos.org/share/browser/lang/java/echo_samples/act9

ポイントとなるのは、act9/src/bin/ 以下に格納したbatやshになります。これらはpackagingすることで以下のように配置されます。

echoes-act9-1.0.0/
  lib/*.jar
  ea9_*.bat
  ea9_*.sh
  echoes-act9.ini
  他、ライセンスやNTサービス登録用のbatファイルなど

Windowsのbatでclasspathを調整する

Windowsでclasspathを調整しているのは ea9_env.bat と ea9_addclp.bat の2つになります。
ea9_env.bat:

set EA9_HOME=%~dp0
set EA9_SVC_NAME=EchoesAct9
set EA9_SVC_DISPLAY_NAME="Echoes Act9"
set EA9_SVC_DESCRIPTION="Echoes Act9 Service"

set JAVA_OPTIONS_SRV=-Xmx200m -Xloggc:"%EA9_HOME%gc.log"

set CLASSPATH=
for %%I in ("%EA9_HOME%lib\*.jar") do call ea9_addclp.bat "%%I"

最後のforで、"lib/*.jar" をワイルドカードで指定することで1ファイルずつ展開て "%I" に格納し、ea9_addclp.bat に渡しています。

ea9_addclp.bat:

SET CLASSPATH=%1;%CLASSPATH%

ea9_addclp.batの中では、単純にCLASSPATH環境変数に渡されてきたファイルパスを追加していきます。
これ、最初はea9_env.batの中だけで完結できるんじゃ・・・と試してたんですが、うまく行かなくて(理由は忘れた)、CLASSPATHの設定だけea9_addclp.batに分離してうまく動作しました。

実際のjava実行用batは以下のようになっていて、ea9_env.batをcallしたらそのままjavaを起動するだけです。
ea9_client.bat:

call ea9_env.bat
java -classpath %CLASSPATH% echoes.act9.client.EchoesClient "%EA9_HOME%echoes-act9.ini"

unixのsh(bash)でclasspathを調整する

unixの場合にclasspathを調整しているのは ea9_env.sh になります。調整箇所だけ抜粋します。
ea9_env.sh:

CLASSPATH=
for i in `/bin/ls lib/*.jar`; do CLASSPATH=$i:$CLASSPATH ; done
export CLASSPATH

lsコマンドの出力結果をCLASSPATHに追加してるだけです。・・・ちょっとlsコマンドの挙動に依存関係が発生してしまうのが気持ち悪いですが、2010年ごろのサンプル作成時は、これでうまく動いてました・・・。

実行用のshは以下のようになっていて、bashの"."でea9_env.shを展開して実行したら、javaを起動するだけです。
ea9_client.sh:

cd `dirname $0`
. ea9_env.sh
java -classpath $CLASSPATH echoes.act9.client.EchoesClient echoes-act9.ini

以上、batやshの機能だけでclasspathを調整するサンプルの紹介でした。

step4 : Maven Application Assemblerを使う

参考:

step3では手作りのshやbatファイルでclasspathを調整してみましたが、Maven Application Assemblerを使うともっとちゃんとした(?)・・・その、多分、もうちょっと依存性を薄めてちゃんと動いてくれる・・・本格的?な?batやshを作ってくれるようです。
原理的には、パッケージングの段階で依存jarを収集して、プリセットされたディレクトリ構成に配置し、それを相対パスで参照するようなclasspathを埋め込んでbat/shを生成します。ですので、bat/sh内で黒魔術を使って動的にjarを探索、classpathを構築してるわけではないです。(生成されたbat/shを見てもらえれば「あ~」と納得していただけるかと。)

ということで、step3で紹介したechoes.act9をappassemblerで構築してみます。

まずpom.xmlのpluginsを以下のように修正します。

  • ポイント1 : appassemblerはあくまでもシェルスクリプトおよび依存jarの収集までを担当するだけです。実際のzip/tarボールへのパッケージングには引き続きmaven-assembly-pluginが必要です。
  • ポイント2 : appassemblerのデフォルトでは、Mavenリポジトリのディレクトリ構成で依存jarが収集されてしまい、それに合わせたclasspathが、appassemblerの生成したbat/sh中にハードコードされます。それだとCLASSPATH環境変数の文字数が、サブディレクトリに区切られる影響でやたらと長くなってしまいますので、今回はjarの収集はassembly側のdependencySetで"/lib"以下にflatに収集させ、appassembler側では"repositoryLayout"と"repositoryName"を"flat"と"lib"にして、assembly側で収集した"/lib"以下に合わせました。同時に、jar収集はassemblyのdependencySetで実施するため、appassembler側は"generateRepository"にfalseを指定してjar収集をしないようにします。
<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>appassembler-maven-plugin</artifactId>
  <version>1.3</version>
  <configuration>

    <!-- appassembler自身は依存jarは収集しない -->
    <generateRepository>false</generateRepository>

    <!-- assembly側のdependencySetで、"/lib" 以下に依存jarがflat構成で収集されるのに合わせる -->
    <repositoryName>lib</repositoryName>
    <repositoryLayout>flat</repositoryLayout>

    <programs>
      <program>
        <mainClass>echoes.act9.server.EchoesServer</mainClass>
        <name>ea9_server</name>
      </program>
      <program>
        <mainClass>echoes.act9.client.EchoesShutdown</mainClass>
        <name>ea9_shutdown</name>
      </program>
      <program>
        <mainClass>echoes.act9.client.EchoesClient</mainClass>
        <name>ea9_client</name>
      </program>
    </programs>
  </configuration>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>assemble</goal>
      </goals>
    </execution>
  </executions>
</plugin>
<plugin>
  <artifactId>maven-assembly-plugin</artifactId>
  <version>2.3</version>
  <configuration>
    <descriptors>
      <descriptor>src/assemble/bin.xml</descriptor>
    </descriptors>
  </configuration>
  <executions>
    <execution>
      <id>make-assembly</id>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
    </execution>
  </executions>
</plugin>

src/bin/以下のsh, batは今回は使いませんので、バッサリディレクトリごと削除します。
続いてassemblyプラグインのdescriptorである src/assemble/bin.xml ファイルを以下のように修正します。
src/assemble/bin.xml:

<assembly>
  <id>bin</id>
  <formats>
    <format>tar.gz</format>
    <format>tar.bz2</format>
    <format>zip</format>
  </formats>
  <fileSets>
    <!-- iniファイルやLICENSEファイルは従来通りパッケージ直下に配置 -->
    <fileSet>
      <directory>${project.basedir}</directory>
      <outputDirectory>/</outputDirectory>
      <includes>
        <include>*.ini</include>
        <include>LICENSE*</include>
      </includes>
    </fileSet>
    <!-- appassemblerにより生成されたbat/shは"/bin"以下に配置 -->
    <fileSet>
      <directory>target/appassembler/bin</directory>
      <outputDirectory>/bin</outputDirectory>
    </fileSet>
  </fileSets>
  <files>
    <file>
      <source>README.txt</source>
      <outputDirectory>/</outputDirectory>
      <filtered>true</filtered>
    </file>
  </files>
  <!-- 依存jarは従来通り"/lib"以下に配置 -->
  <dependencySets>
    <dependencySet>
      <outputDirectory>/lib</outputDirectory>
      <includes>
        <include>*:jar</include>
      </includes>
    </dependencySet>
  </dependencySets>
</assembly>

ビルドしてみます。

$ mvn package
$ tar ztf target/echoes-act9-1.0.0-bin.tar.gz
echoes-act9-1.0.0/echoes-act9.ini
echoes-act9-1.0.0/LICENSE.txt
echoes-act9-1.0.0/LICENSE_slf4j.txt
echoes-act9-1.0.0/bin/
echoes-act9-1.0.0/bin/ea9_client
echoes-act9-1.0.0/bin/ea9_client.bat
echoes-act9-1.0.0/bin/ea9_server
echoes-act9-1.0.0/bin/ea9_server.bat
echoes-act9-1.0.0/bin/ea9_shutdown
echoes-act9-1.0.0/bin/ea9_shutdown.bat
echoes-act9-1.0.0/lib/mina-core-1.1.7.jar
echoes-act9-1.0.0/lib/slf4j-api-1.6.1.jar
echoes-act9-1.0.0/lib/mina-integration-jmx-1.1.7.jar
echoes-act9-1.0.0/lib/log4j-1.2.16.jar
echoes-act9-1.0.0/lib/slf4j-log4j12-1.6.1.jar
echoes-act9-1.0.0/lib/echoes-act9-1.0.0.jar
echoes-act9-1.0.0/README.txt

実行結果については省略します。
注意点:

  • unix用shellscriptについては実行権限がつかないため、展開後に手動でchmodするか"sh bin/xxxx"とする必要があります。もしかしたら設定で修正できるかも?
  • step3と異なり、echoes-act9.iniをコマンドラインから手動で指定する必要があります。このあたりは、javaコマンドに引数を設定することが可能ですので、設定次第で省略出来るかもしれません。

stepX(おまけ) : 複数のjarを1つのjarに統合する各種技術

One-JARやfat-jar、あるいはmaven-assembly-pluginの"jar-with-dependencies" descriptorでは、依存するjarを1つのjarに統合するアプローチを採用しています。その中でもさらに以下の2つのアプローチがあるようです。

  1. One-JARが採用している、jarの中にjarを入れ子にして、専用のクラスローダを埋め込む。
  2. 単純に依存jarを全部展開して、1つのjarにアーカイブし直す。(maven-assembly-pluginの"jar-with-dependencies" descriptorがこのアプローチ・・・っぽい。多分。)

確かに単純に実行の容易さだけを考えるとCoolでSmartに見えなくもないのですが、本来は別個で扱われるべきアーカイブ内容を、無理やり1つに統合してしまうので、デメリットも存在します。例えば個別のjarファイル中のマニフェスト情報はロストしてしまう可能性が高いです。これらの情報を扱うようなアプリでは致命的な問題になります。One-JARが採用する、専用のクラスローダによるjarの入れ子の場合、jar中に埋め込んだ設定ファイルを読み出すようなプログラムではクラスローダ周辺のトラブルが発生する可能性が高くなります。
便利ではありますが、落とし穴も大きい可能性がありますので、採用する場合は事前に入念な下調べが必要になると思われます。時間の都合上、本記事では参考URLを紹介するのみに止めます。



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2013-07-28 15:38:48
md5:52dea4b7cc4a5d33ea1174ba52ddded9
sha1:93095dd11c0338b3930b949d7ac9cff8cf57b616
コメント
コメントを投稿するにはログインして下さい。