オーバーロードされたメソッドの呼び出しを正しく逆コンパイルできる Java デコンパイラはありますか?[閉まっている]
-
27-09-2019 - |
質問
次の (私見では単純な) 例を考えてみましょう。
public class DecompilerTest {
public static void main(String[] args) {
Object s1 = "The", s2 = "answer";
doPrint((Object) "You should know:");
for (int i = 0; i < 2; i++) {
doPrint(s1);
doPrint(s2);
s1 = "is";
s2 = new Integer(42);
}
System.out.println();
}
private static void doPrint(String s1) {
System.out.print("Wrong!");
}
private static void doPrint(Object s1) {
System.out.print(s1 + " ");
}
}
デバッグ情報なしでソース/ターゲット レベル 1.1 でコンパイルします (つまり、ローカル変数情報は存在しないはずです) を確認して、逆コンパイルしてみてください。Jad、JD-GUI、Fernflower を試してみましたが、どれも少なくとも 1 つの呼び出しが間違っていました (i.e.プログラムは少なくとも一度は「間違っている!」と印刷しました)
間違ったオーバーロードを呼び出さないように正しいキャストを推論できる Java デコンパイラは本当にないのでしょうか?
編集: Java6 固有の高速検証情報が存在しないように、レベル 1.1 をターゲットにします。これにより、s1 が次のように宣言されているという手がかりが逆コンパイラに与えられる可能性があります。 Object
そしてそうではありません String
. 。逆コンパイラは、特に多くの難読化ツールが情報を削除するため、この情報がなくてもコードを逆コンパイルできる必要があります (元の変数の型を取得する必要はありませんが、同じ動作を示します)。
逆コンパイラが間違っていたこと:
- 彼らはキャストを逃した
(Object)
最初の電話で。 - 彼らは次のタイプを推測しました
s1
することがString
, 、ただし、への呼び出しにキャストを追加するのを忘れていましたdoPrint
(そのため、オブジェクト バージョンの代わりに文字列バージョンが呼び出されます)。 - 1 つのひどいもの (私はリストすらしていません) のタイプを推測することさえできます。
s2
String であるため、コードがコンパイル不能になります。
いずれにせよ、このコードは決して String
オーバーロードしましたが、逆コンパイルされたコードはオーバーロードしました。
解決
クラカタウのが正しく、すべてのオーバーロードメソッドは、ほとんどの逆コンパイラは誤解プリミティブ型、上オーバーロードささえメソッドを処理します。コードは、必要以上に雑然とすることができるので、それは常に、呼び出されたメソッドの正確な型に引数をキャストするが、少なくとも、それが正しい。
情報開示:私はクラカタウの著者だ。
他のヒント
ハローmihi、
後半応答のため申し訳ありません。私は http://www.reversed-java.com/から私の答えをコピーしていますfernflower /フォーラム?threadfolder = 2_DEする
あなたの問題は、実際にはよく知られているものです。レッツは、参照してください。
1)は、純粋なバイトコードは、第1パスS1及びS2内のオブジェクトとして宣言され、オブジェクト変数の種類に関する情報が含まれていない。
2)逆コンパイラは、各変数Fernflowerに実装(=「最も狭いタイプの原則」)に可能な限り最高のタイプを割り当てるために努力しています。だから、S1、S2は、正しく文字列のインスタンスとして識別されます。
3)doPrintの呼び出しは私たちに正しい方法
への直接リンクを与えます
プライベートの静的な無効doPrint(オブジェクトS1)
4)すべてOK、これまでに、右?今、私たちは、オブジェクトを期待する関数に渡された文字列変数S1を、持っています。我々はそれをキャストする必要がありますか?オブジェクトは、文字列のスーパータイプがあるようでないような、あなたは、と思うだろう。そして、まだ我々はやる - 同じ名前と異なるパラメータの署名と同じクラス内の別の機能があるため。私たちは、だから、キャストが必要とされているかどうか、調べるためにクラス全体を分析する必要があります。
5)一般的には、それは我々がJavaランタイムを含むすべてのライブラリ内のすべての参照クラスを分析する必要があるということです。仕事の膨大な負荷!確かに、この機能はFernflowerの一部のアルファ版で実装されましたが、理由はパフォーマンスとメモリのペナルティをまだ生産でそれを行っていません。その他上記の逆コンパイラは、設計によって、この能力を欠いています。
希望私は物事を少し明らかにしています)。
また、逆コンパイルするためのJadClipse Eclipseプラグインを使用して、試してみたいことがありますJODE逆コンパイラを提供します。 JADファイルはあきらめたときに私はそれを使用します。
またDAVA逆コンパイラは、すすを使用する - 私が最後に見た時は - 元のJavaコードを再構築するには非常に野心的でした。私はあなたの例を試していませんが、あなたは見てしたいことがあります。 http://www.sable.mcgill.ca/dava/する
プロキオンのは正しくオーバーロードされたメソッド呼び出しを処理する必要があります。クラカタウのように、プロキオンは当初、正確にターゲットメソッドと一致しないすべてのメソッドの引数のキャストを挿入します。しかし、これらのほとんどは特定して排除はキャストを冗長することを逆コンパイルの後の段階中に削除されます。それはそうすることが、別の方法への結合の呼び出しにはなりませんことを確認できた場合プロキオンにのみコールの引数のキャストを削除します。メソッドを宣言.class
が解決できない場合たとえば、それは過負荷が競合する可能性のあるものを知る方法がないので、すべてのキャストを削除しようとしません。
以前の回答に追加:2015 年 3 月現在の最新の逆コンパイラーのリストは次のとおりです。
- プロキオン
- CFR
- JD
- シダフラワー
これらはすべて、オーバーロードされたメソッドをサポートしています。
上記の逆コンパイラはインストール不要でオンラインでテストでき、知識に基づいて独自の選択を行うことができます。クラウド内の Java デコンパイラー: http://www.javadecompilers.com/