2013-02-26 5 views
6

ビルドチェーン内のいくつかのjarファイルを再コンパイルする必要があるかどうかを判断しようとしています。たとえば、次の構造を持つとjarファイルが変更されたときにjarファイルをコンパイルし、再コンパイルしました。親クラス/インタフェースが変更された場合、クラスのバイトコードは変更できますか?

瓶1:

public class Foo /* impl*/ 

瓶2:

public class Bar extends Foo /*impl*/ 

2クラス間の契約を想定するとは、すなわち変更されません。抽象メソッドが追加されたり、インタフェースにメソッドが追加されたりします。

jar 2を再コンパイルする必要はありますか?すなわち、 Foo内でプライベートメソッドを変更した場合、Barを再コンパイルする必要がありますか?

1つのバンチを変更した後、2つのクラスのバイトコードを比較することでこれをテストしましたが、期待通りに変更されませんでした。しかし、私の同僚は、契約が変わっていないにもかかわらず、それが動作するためにすべてを再コンパイルしなければならない状況に遭遇したと主張しますが、理由は何かを覚えていません。それは必要ではないはずです。 スーパークラスに変更を加えると、2つの間のインターフェイスが同じままであっても、サブクラスを再コンパイルする必要がありますか?

答えて

6

だがFooはオープ​​ンソース組織によって解放されたとしましょう使用されます。さまざまな企業によって実装されたFooという数千のサブクラスがあります。

Fooにいくつかの変更が加えられ、新しいバージョンがバイナリ形式でリリースされると、すべての企業がコードを再コンパイルする必要がありますか?もちろん違います。(すべてのコードを常に再コンパイルしますが、それは必須ではありません - Fooの新しいjarファイルは問題を起こさずに単純に削除できます)

これはバイナリ互換性の問題です。仕様を変更してFooへの変更が安全であることを確認してください。 http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html

+0

リンクをありがとう、私はソースが変更されない限り、クラスファイルを変更する必要はないと思っていたと思います。しかたがない。 – Andrew

3

通常、依存するクラスを再コンパイルする必要があります。ただし、Fooが使用するメソッドまたはフィールドを変更していない場合は、BarFooが変更されたときにBarを再コンパイルする必要はありません。 FooBarによって呼び出されるメソッドprotected int foo()があったが、たとえば

あなたはprotected String foo()にそれに署名を変更したり、Barを再コンパイルする必要がありprivateにその可視性を変更しました。この場合、Barはコンパイルできません。コードを変更する必要があります。

しかしBar場合メソッドfoo()を使用していないか、foo()の唯一の実装の詳細が変更された場合は、再コンパイルせずにBarを使用することができます。

+0

バーが使用するFooの定数値を変更するには、再コンパイルも必要です。 – jtahlborn

+2

また、Javaには[バイナリ互換性](http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html)のための明確なルールがあります。 – jtahlborn

+0

@jtahlborn、ルールへのリンクありがとうございます。非常に便利。 – AlexR

2

間違いなく、jarファイルにパッケージ化されたフレームワーク(Fooのような契約を持つ多くのクラスを含む)を使用でき、ソースからコンパイルする必要はありません。しかし、間接的に契約が直接変更されていないことを絶対に確信する必要があります。間接的な変更のいくつかのexmaple:

public class Foo { //v1 
    public static final int CONSTANT = 1;   
} 

public class Foo { //v2 
    public static final int CONSTANT = 2;   
} 

public class Bar extends Foo { 
    private int a(int value) { 
     switch (value) { 
      case CONSTANT: 
       return 1; 
     } 
     return 2; 
    } 
} 

あなたはクラスのバーを再コンパイルしていない場合、それはまだ値1

+0

これは、Bar.classファイルの中に 'CONSTANT' intの値があることを意味しますか?私の直感は、それが 'Foo/CONSTANT'に対する言い回ししか持たず、実行時にそれに応じて更新されると言っています。それがなぜそうではないか、どんな考えですか?おそらくyesよりも_switch_以外のものを使用する場合は – Andrew

+0

としてください。スイッチ命令は明示的な数値を必要とするため、コンパイル時に実行時にCONSTANTフィールドから値を読み取ることはできません。 – ijrandom

関連する問題