はじめに
Javaのプロジェクトの仕事の中で、ソースコードをjarファイルとしてビルドをして、それをサーバーにデプロイしていました。そのデプロイされたjarファイルの中身をテスト用に書き換えたくなった時に、少し嵌ったのでここに解決方法をメモしておきます。
尚、本記事ではSpringフレームワークのプロジェクトを例として扱います。jarファイルの解凍時のディレクトリは、以下のようになっています。
┣ BOOT-INF/
┣ classes
┗ application.properties <- *このファイルを書き換えたい*
┗ lib
┗ {使用してるライブラリのjar}
┣ META-INF/
┣ maven/
┗ {pom.xmlとか}
┗ MANIFEST.MF <- マニフェストファイル
┗ org/
┗ {classファイルがいっぱい}
具体的には、/BOOT-INF/classes/application.properties
を書き換えようとして、失敗しました。
失敗例
解凍してから、zipコマンドで固める
jarファイルは実質的にはzipファイルと変わらないので、zip
コマンドでjarファイルを解凍して、ファイルを修正し、再度zip
コマンドで固め直そうとしました。
この結果できたファイルを基にアプリをjava -jar
コマンドで起動しようとすると、以下のエラーが出ました。
Exception in thread "main" java.lang.IllegalStateException: Failed to get nested archive for entry BOOT-INF/lib/bcpkix-jdk15on-1.60.jar
at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchive(JarFileArchive.java:108)
at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchives(JarFileArchive.java:86)
at org.springframework.boot.loader.ExecutableArchiveLauncher.getClassPathArchives(ExecutableArchiveLauncher.java:70)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:49)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
Caused by: java.io.IOException: Unable to open nested jar file 'BOOT-INF/lib/bcpkix-jdk15on-1.60.jar'
at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(JarFile.java:256)
at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(JarFile.java:241)
at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchive(JarFileArchive.java:103)
... 4 more
Caused by: java.lang.IllegalStateException: Unable to open nested entry 'BOOT-INF/lib/bcpkix-jdk15on-1.60.jar'. It has been compressed and nested jar files must be stored without compression. Please check the mechanism used to create your executable jar file
at org.springframework.boot.loader.jar.JarFile.createJarFileFromFileEntry(JarFile.java:284)
at org.springframework.boot.loader.jar.JarFile.createJarFileFromEntry(JarFile.java:264)
at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(JarFile.java:252)
... 6 more
エラーメッセージにnested jar files must be stored without compression
とある通り、BOOT-INF/lib
以下のライブラリのjarファイル群を圧縮してしまったことで(?)うまくjarファイルとして読み込まれなかったようです。
解凍してから、jarコマンドで再作成
単純なzipコマンドでダメなら、jarコマンドでjarファイルの作成を試みてみます。
jar cvfm xxx.jar ./META-INF/MANIFEST.MF ./
上のコマンドで作成したjarファイルを基に起動しようとすると、以下のエラーが出ました。
no main manifest attribute, in xxx.jar
ちゃんとオプションでマニフェストファイルを指定しているのに、上手く読み込まれていないようです(この現象の直接的な原因は、未解決です)。
成功例
zipコマンドで、解凍せずに中身を入れ替える
jarファイルを解凍せずに中身を書き換えることで、上記の問題をクリアしました。
まず、作業しているローカルの場所で、書き換えたいファイルとそれが置かれているディレクトリを再現します。
私は今回BOOT-INF/classes/application.properties
というファイルを書き換えたかったので、それを作ります。
mkdir -p BOOT-INF/classes && touch ./BOOT-INF/classes/application.properties
このローカルのapplication.properties
ファイルを書き換えたら、それをzipに取り込みます。
取り込みたいzipファイル(xxx.jar
)を同ディレクトリに持ってきて、以下のコマンドで取り込みます。
zip ./xxx.jar ./BOOT-INF/classes/MANIFEST.MF
この結果できたjarファイルは、一度も解凍してないためかエラーが起こらず、問題なく動かすことができました。
ついでに
上に記したのは、jarファイルの中身を書き換える方法でした。
中身を書き換えるのではなく、ただ見るだけであれば、以下のコマンドで見れます。
jar tf xxx.jar
中身を確認するためにわざわざjarファイルを解凍していたら、上司に怒られました。