Java/JVM仕様の不完全さという、次のような奇妙なケースに直面しました。今)Javaでインタフェースする静的メソッドを持つクラスを変更するバイナリ互換性
User.mainを(実行public interface Class {
public static void foo() {
System.out.println("hi");
}
}
:ユーザーを再コンパイルせずにインターフェースするクラスを再コンパイル後
public class Class {
public static void foo() {
System.out.println("hi");
}
}
public class User {
public static void main(String[] args) {
Class.foo();
}
}
:私たちはクラスを(我々は、Java 1.8とのHotSpotを使用します)があるとし同じ出力 'hi'を生成します。これは明白なようだが、私はそれがでIncompatibleClassChangeErrorで失敗する期待と理由です:私はインターフェイスにクラスを変更するとJVM 5.3.5#3 statementによるとバイナリ互換性であることを知っている
:
クラスまたはインタフェース場合実際にはCの直接スーパークラスという名前のインターフェイスは、IncompatibleClassChangeErrorをスローします。
しかし、我々はクラスの後継を持っていないと仮定してみましょう。メソッドの解決方法については、JVM仕様を参照する必要があります。 最初のバージョンは、このバイトコードにコンパイルされています
public static void main(java.lang.String[]);
Code:
0: invokestatic #2 // Method examples/Class.foo:()V
3: return
だから我々はここclasspoolで「CONSTANT_Methodref_info」と呼ばれるものを持っています。
invokestaticの動作を引用しましょう。
...そのインデックスにおける実行時定数プール項目は、名前と記述(§4.3を与える方法又はインタフェース方法(§5.1)へのシンボリック参照しなければなりません。 3)と、メソッドが見つかるクラスまたはインタフェースへのシンボリックな参照。指定されたメソッドは解決済み(§5.4.3.3)です。
したがって、JVMはメソッドとインターフェイスのメソッドを異なる方法で処理します。私たちの場合、JVMはメソッドがクラスのメソッド(インタフェースではない)であるとみなします。
JVMの仕様によれば、JVMは、次の文に失敗しなければならない:
1)Cインターフェイスである場合、この方法の解像度がでIncompatibleClassChangeErrorがスロー JVMは、それに応じて分解能5.4.3.3方法は、それを解決しようと。
Classは実際にクラスではなくインターフェイスなので、
残念ながら、Java言語仕様第13章バイナリ互換性でクラスをインタフェースに変更することのバイナリ互換性に関する記述は見つかりませんでした。さらに、同じ静的メソッドを参照するというようなトリッキーなケースについては何も言及されていません。
誰かがそれについて詳しく説明して、私が何かを見逃したら私に見せてもらえますか?
ところで、私は[言及](https://wiki.eclipse.org/Evolving_Java-based_APIs_2#Evolving_API_packages)を見つけました。 'APIクラスインターフェイスの性別の変更は、クラス/インタフェースは、クライアントによって使用されますが、クライアントでは使用されません。これは、インタフェースで宣言されたメソッドを呼び出すためのJava VMバイトコードが、クラスで宣言されたメソッドを呼び出すために使用されたバイトコードと異なるためです。しかし、それは非公式なものです。 –