42023


windowsのdllファイルとかだと右クリックプロパティからバージョン番号を見れるものがありますが  
あんな感じの情報をjavaのclassファイルに埋め込みたいです。  
windowsとeclipseで開発してますがそのようなことは可能でしょうか。  
可能ならやり方を教えてください。  
よろしくお願いします。


CC BY-SA 3.0
2018-02-23T03:56:52.117
41948
2018-02-26T22:17:46.643
18637
question
java eclipse
javaのclassファイルにバージョン情報を埋め込みたい


`.dll`ファイルに相当するのは`.class`でなく`.jar`ファイルになるかと思います。

JARファイルの仕様では`META-
INF/MANIFEST.MF`ファイルに、[実装バージョン](https://docs.oracle.com/javase/jp/8/docs/technotes/guides/versioning/spec/versioning2.html#wp90468)を記述する[`Implementation-
Version`セクション](https://docs.oracle.com/javase/jp/8/docs/technotes/guides/jar/jar.html#Main_Attributes)があります。  
これが[DLLのバージョン情報](https://ja.wikipedia.org/wiki/%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9_\(Windows\)#%E7%A8%AE%E9%A1%9E)に近いものかと考えます。

JARファイルへのマニフェストファイル追加は[`jar`コマンド](https://docs.oracle.com/javase/jp/7/technotes/tools/windows/jar.html)の`m`オプションで行えます。

あるいは、 `maven-jar-plugin`
を利用するのであれば、[`addDefaultImplementationEntries`を`true`に設定](https://maven.apache.org/shared/maven-
archiver/examples/manifest.html)することでプロジェクトのバージョンを自動で`Specification-
Vendor`に設定することも出来ます。

* * *

ただし、Javaプログラマに「何によってJARファイルのバージョン識別を行うか」という質問をしたとき、回答で最も多いのは(上記のような`MANIFEST.MF`のエントリによってではなく)
**JARファイルのファイル名によって** 識別する、だろうと思われます。

Javaではバージョン管理対象となるようなJARファイルの生成には[Maven](https://maven.apache.org/)を使用するのが一般的で、これを利用してJARファイルを生成した場合、デフォルトでファイル名にバージョン番号が付与されます。

例えば[こちら](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22junit%22%20AND%20a%3A%22junit%22)ではJUnitのバージョンごとのファイルがダウンロードできますが("Download"の"jar"リンク)、バージョン`4.12`であれば`junit-4.12.jar`,
バージョン`3.8.1`であれば`junit-3.8.1.jar`という名前になっているのが確認できるかと思います。

Maven形式のプロジェクトは、Eclipseなど一般的なJava用IDEで取り扱うことができます。


CC BY-SA 3.0
2018-02-23T19:37:25.260
41964
2018-02-23T19:37:25.260
2808
41948
answer


1案目として考えられるのは、一般的なファイルシステムから標準的に取得できる情報(具体的には「ファイル作成日時」など)でバージョニングを行う方法です。  
メリットは取り扱いが簡単なこと、デメリットは他のアプリケーション(圧縮展開ツールやファイル転送ツール)で意図せずとも情報が書き換えられてしまう可能性が有ること、でしょうか。  
Javaでは
[`BasicFileAttributeView`](https://docs.oracle.com/javase/jp/9/docs/api/java/nio/file/attribute/BasicFileAttributeView.html)
インタフェース経由などでread/writeできます([実装例](https://docs.oracle.com/cd/E26537_01/tutorial/essential/io/fileAttr.html#basic))。

2案目として考えられるのは、([ファイルシステムがサポートしている](https://stackoverflow.com/a/15829683/4506703)のなら)
ユーザー定義属性としてバージョニング情報を格納することです。  
こちらは[`UserDefinedFileAttributeView`](https://docs.oracle.com/javase/jp/9/docs/api/java/nio/file/attribute/UserDefinedFileAttributeView.html)インタフェース経由でread/writeします([実装例](https://docs.oracle.com/cd/E26537_01/tutorial/essential/io/fileAttr.html#user))。  
メリットは本来(すなわちバージョニング)のための情報として保持できること、デメリットは1案目より低いポータビリティでしょうか。


CC BY-SA 3.0
2018-02-26T14:51:41.937
42022
2018-02-26T14:51:41.937
2808
41948
answer


javapコマンドでclassファイルを逆アセンブルする方法もあります．  
windowsで動作確認していませんが，Linuxでは以下のように  
コンパイル前のファイル名，クラス名，コンストラクタ，フィールド名，メソッド名が  
が確認できます．

[code]

    $ javap Hello.class
    Compiled from "Hello.java"
    class Hello {
      public static final java.lang.String VERSION;
      Hello();
      public void sayHello();
    }
    
[/code]

-vオプションを付けるとより詳細に表示されます．
[code]

    $ javap -v Hello.class
    ...
      public static final java.lang.String VERSION;
        descriptor: Ljava/lang/String;
        flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
        ConstantValue: String 1.0.0
    ...
    
[/code]

このように，定義した変数の値も確認できるので  
(ここでは VERSION = "1.0.0" とした)  
コンパイル前にjavaファイルにバージョン情報を埋め込むことで  
javapコマンド経由で確認することもできます．


CC BY-SA 3.0
2018-02-26T15:33:10.547
42023
2018-02-26T15:33:10.547
7770
41948
answer


アノテーションを使うのはどうでしょう。

Version.java:

[code]

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Version {
        String value();
    }
    
[/code]

Main.java:

[code]

    @Version("1.0")
    public class Main {
        public static void main(String[] args) {
            Class c = Main.class;
            Version v = (Version) c.getAnnotation(Version.class);
            System.out.println(v.value());
        }
    }
    
[/code]


CC BY-SA 3.0
2018-02-26T22:17:46.643
42026
2018-02-26T22:17:46.643
15325
41948
answer