実行可能JARの実行時ファイルパスを取得する
  Java, プログラミング

実行プログラムと同じ場所にある設定ファイルを読み取るために、実行プログラムのファイルパスを取得したいことありますよね。

Javaの実行プログラム(実行可能JARファイル)の実行時ファイルパスを取得する方法を紹介します。

ProtectionDomainとCodeSource

Javaではクラスのドメイン属性から、そのクラスが読み込まれた位置を取得することができるようになっています。

ClassインスタンスのgetProtectionDomain()メソッドによってProtectionDomainインスタンスを取得できます。

次に、ProtectionDomainインスタンスのgetCodeSource()メソッドによってCodeSourceインスタンスを取得できます。

このCodeSourceインスタンスは、クラスの読み込み位置(URL)を保持しています。CodeSourceインスタンスのgetLocation()メソッドによって、はじめに指定したClassインスタンスを格納しているJARファイルのパスを取得することができます。

実際のコードは以下のようになります。

Sample.java
package com.example; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; import java.security.CodeSource; import java.security.ProtectionDomain; public class Sample { public static void main(String[] args) throws Exception { Path path = getApplicationPath(Sample.class); System.out.println("path=" + path); } public static Path getApplicationPath(Class<?> cls) throws URISyntaxException { ProtectionDomain pd = cls.getProtectionDomain(); CodeSource cs = pd.getCodeSource(); URL location = cs.getLocation(); URI uri = location.toURI(); Path path = Paths.get(uri); return path; } }

実行可能JARファイルを作成して動かしてみる

ソースコード com\example\Sample.java をコンパイルしておきます。(C:\temp\srcにソースコードを置いています。)

C:\temp>javac src\com\example\Sample.java

実行可能JARファイルを作成するために、メイン・クラスを指定したマニフェストファイルを用意します。(C:\temp\\MANIFEST.MFに置きました。)

MANIFEST.MF
Main-Class: com.example.Sample

jarコマンドで実行可能JARファイルを作成します。

C:\temp>jar cfm sample.jar MANIFEST.MF -C src .

これで、実行可能なsample.jarが出来上がります。

メモ
ここまでの手順はコマンドラインを使わずに、EclipseなどのIDEで実行可能JARファイルを作成しても構いません。

sample.jarを実行して出力を確認します。

C:\temp>java -jar sample.jar
path=C:\temp\sample.jar

ちゃんと、実行可能JARファイルのパスが表示されていますね。

EXE化してもファイルパスを取得できます

このProtectionDomainを使って実行時ファイルパスを取得する方法は、exewrapを使ってJARファイルをEXE化した場合でも正しく動作します。

C:\temp>exewrap sample.jar
Architecture: x86 (32-bit)
Target: Java 5.0 (1.5.0.0)
sample.exe (32-bit) version 0.0.0.1

C:\temp>sample.exe
path=C:\temp\sample.exe

Eclipseから実行した場合は

開発中はJARやEXEにせずに開発環境から直接実行することが多いですよね。 Eclipseから実行した場合に取得されるパスがどのようになるのか見てみましょう。

path=C:\workspace\sample\bin

このような出力結果になりました。sampleというのはプロジェクト名です。 binはプロジェクトの既定の出力フォルダー(Default output folder)です。

Eclipseの場合はファイルパスではなくフォルダーパスになってしまうのは仕方ないですね。

getParent()で 1つ上のフォルダーを参照すると扱いやすくなる

取得したPathgetParent()メソッドを呼んで、1つ上のフォルダーを取得すると扱いやすいフォルダーパスになります。(JAR/EXE/Eclipseで条件分岐させることなく共通のコードで済みます。)

1つ上のフォルダーを取得すると、それぞれ以下のようになります。

  • C:\temp\sample.jarC:\temp (JARファイルのあるフォルダー)
  • C:\temp\sample.exeC:\temp (EXEファイルのあるフォルダー)
  • C:\workspace\sample\binC:\workspace\sample (プロジェクトのルートフォルダー)

このフォルダーをプログラムの基準パスとして、ここに設定ファイルなどを配置するように構成すると便利です。