47
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Systemi(株式会社システムアイ)Advent Calendar 2024

Day 23

フフフ、ついに奥の手 javap を使う時が来たようだな・・・

Last updated at Posted at 2024-12-22

はじめに

しょうもないタイトルから始まってますが、内容もしょうもないです。時間に余裕のない方は「そっ閉じ」してください。

実は先日(2024/12/21)、私が関わっているプロジェクトのリリース作業で問題が発生いたしまして、つい先程(2024/12/22)まで色々と調査、今後の方針等の対応を行っていました。
色々と思うところがありまして、記事として残しておいてもいいかなと思い至った結果、急遽記事の内容を変更してお届けしております。

いいですか?決して時間が足りなくなったわけじゃないですからね。

前提条件

よくあるアーキテクチャなのですが、この話で登場するシステムでは「ライブラリ管理システム」といったビルド資産を一括管理するシステムがありまして、そのシステム経由でライブラリリリースが行われています。

何が起こったのか?

Production 環境に既にリリースされている jar ファイルと、ライブラリ管理システム上に保管されている jar ファイルのハッシュ値が異なるといった事象が発生しました。おい!なんでやねん・・・。

# 今回のリリースファイル
0ddb496abee187fb0b5acd27947a5e77 /production/hogehoge/xxx_1.jar
4478efb2cedb25882d6d5d842af65966 /production/hogehoge/tmp/release/xxx_1.jar

# 今回修正していないファイル
cf4dd51e1c28a9d201805ad648e74721 /production/hogehoge/xxx_2.jar
bdf1959685c4ce0095f0bfb490e567af /production/hogehoge/tmp/release/xxx_2.jar

# develop と production のライブラリ管理システム上は同じ
bdf1959685c4ce0095f0bfb490e567af /develop/hogehoge/xxx_2.jar
bdf1959685c4ce0095f0bfb490e567af /develop/hogehoge/tmp/release/xxx_2.jar

当然ですが xxx_2.jar は、ライブラリ管理システムもファイルは更新していません。

この問題の経緯については、マジしょうもない理由のため言及しません。またの機会に。

Misson!! 稼動中のライブラリを担保せよ!

上記の通り、Production 環境だけが、どのライブラリとも一致していない状況であり「デグレードなのか?」と、現場に戦慄が走ります。気絶する人はいませんでした。
当然ながら既に稼働中のシステムですから、「まぁこっちが最新やろ」の勢いだけで資産を更新するわけにもいきません。

[1st] -> unzip/md5sum

ある程度の java 知識がある方であれば、すぐ思いつく手段かと思います。
jar ファイルは zip によって圧縮されたファイルであり、unzip 等のコマンドで class ファイルを展開して、class ファイルのハッシュ値を取り比較する。といった手段があります。

jarコマンドは、ZIPおよびZLIBの圧縮形式に基づいた汎用のアーカイブおよび圧縮ツールです。

[2nd] -> javap(※タイトルの回収ポイント)

上記手段が一致していれば、大抵は納得してもらえるとは思います。ただし万が一、結果が異なっていた時に、そもそもどうデグレードしているのかコードレベルで解析しなさい!となった時に備え、私はこう構えていたのです・・・。

フフフ、ついにあのコマンド(javap)を使う時が来たようだな

javap コマンドとは

まぁ調べればわかる事ではあるのですが、javap コマンドは javac でコンパイルされた class ファイルを逆アセンブルするコマンドです。

Java の逆アセンブルとは、雑に言うとコンパイルされた class ファイル(JVM 中間コード)から、ギリ人間が読めそうな JVM アセンブリコードに変換することです。

どんな感じで出力されるの?

下記のような JVM アセンブリコードが出力されます。見ての通りメソッドのシンボル単位でコードが出てくるため、これと java ソースコードを睨めっこしながら頑張ってデグレードした箇所を特定しましょう!

kook@vdeb:~/workspaces/test/classes$ javap -c xxx.class 

Compiled from "xxx.java"
public class xxx {
  public xxx();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static boolean doSomething1(java.lang.String);
    Code:
       0: iconst_1
       1: ireturn

  public static void doSomething2(java.lang.String[]);
    Code:
       0: aload_0
       1: arraylength
       2: iconst_4
       3: if_icmpge     14
       6: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
       9: aload_0
      10: arraylength
      11: invokevirtual #13                 // Method java/io/PrintStream.print:(I)V
      14: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1
       1: ldc           #19                 // int 1000000
       3: invokestatic  #20                 // InterfaceMethod java/util/stream/IntStream.range:(II)Ljava/util/stream/IntStream;
       6: invokedynamic #26,  0             // InvokeDynamic #0:accept:()Ljava/util/function/IntConsumer;
      11: invokeinterface #30,  2           // InterfaceMethod java/util/stream/IntStream.forEach:(Ljava/util/function/IntConsumer;)V
      16: return
}

あとがき

結論からいうと、ざんねんながら今回のインシデントは javap コマンドを使って確認するまでにはなりませんでした。

そもそも、こんな状況になるような管理してんなよって話でしょうけど、みなさんも明日は我が身です。万が一同じ状況に至り、リリース済ライブラリの担保が必要だとなった時、この記事を思い出していただければ幸いです。

ちなみに、本来 javap はこんな用途で使うものではありません

47
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?