9

この(IMHOの単純な)例を考えてみましょう。

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つの呼び出しが間違っていました(つまり、プログラムが少なくとも1回は「Wrong!」と出力しました)。

間違ったオーバーロードを呼び出さないように正しいキャストを推測できるJavaデコンパイラーは本当にありませんか?

編集:ターゲットレベル1.1で、Java6固有の高速検証情報が存在しないようにします。Objectこれにより、逆コンパイラーに、s1がとしてではなくとして宣言されているという手がかりが得られる可能性がありStringます。逆コンパイラーは、この情報がなくてもコードを逆コンパイルできるはずです(必ずしも元の変数タイプを取得する必要はありませんが、同じ動作を示します)。特に、多くの難読化ツールがコードを削除するためです。

逆コンパイラが間違っていたもの:

  • 彼ら(Object)は最初の電話でキャストを逃した。
  • 彼らはのタイプを推測しましたs1String、への呼び出しにキャストを追加するのを忘れていましたdoPrint(オブジェクトバージョンの代わりに文字列バージョンが呼び出されるように)。
  • 1つのくだらないもの(私はリストしていません)は、タイプs2が文字列であると推測し、コンパイルできないコードを引き起こします。

いずれにせよ、このコードはStringオーバーロードを呼び出すことはありませんが、逆コンパイルされたコードは呼び出しました。

4

5 に答える 5

9

ハローミヒ、

返事が遅くなってごめん。http://www.reversed-java.com/fernflower/forum?threadfolder=2_DEから回答をコピーしています

あなたの問題は実際にはよく知られているものです。どれどれ:

1)純粋なバイトコードにはオブジェクト変数のタイプに関する情報が含まれていないため、最初のパスでs1とs2がオブジェクトとして宣言されます。

2)逆コンパイラーは、各変数に可能な限り最良の型を割り当てようと努力しています(= Fernflowerで実装されている「最も狭い型の原則」)。したがって、s1とs2はStringのインスタンスとして正しく識別されます。

3)doPrintを呼び出すと、正しいメソッドへの直接リンクが得られます
private static void doPrint(Object s1)

4)これまでのところすべて大丈夫ですよね?これで、オブジェクトを期待する文字列変数s1が関数に渡されました。キャストする必要がありますか?ObjectはStringのスーパータイプであるため、そうではないと思います。それでも、同じクラス内に同じ名前と異なるパラメーターシグネチャを持つ別の関数があるためです。したがって、キャストが必要かどうかを確認するために、クラス全体を分析する必要があります。

5)一般的に言えば、Javaランタイムを含むすべてのライブラリで参照されているすべてのクラスを分析する必要があることを意味します。膨大な量の作業!実際、この機能はFernflowerの一部のアルファ版で実装されていましたが、パフォーマンスとメモリのペナルティのため、まだ本番環境では実装されていません。他の言及された逆コンパイラは、設計上この機能を欠いています。

私が物事を少し明確にしたことを願っています:)

于 2010-06-10T10:51:17.490 に答える
5

Krakatauは、ほとんどの逆コンパイラーが間違っているプリミティブ型でオーバーロードされたメソッドを含め、すべてのオーバーロードされたメソッドを正しく処理します。呼び出されたメソッドの正確なタイプに常に引数をキャストするため、コードは必要以上に乱雑になる可能性がありますが、少なくともそれは正しいです。

開示:私はKrakatauの作者です。

于 2014-03-10T16:38:39.413 に答える
3

逆コンパイル用のJadClipseEclipseプラグインは、JODE逆コンパイラーも提供します。これを試してみてください。ジェイドが諦めたときに使います。

また、DavaデコンパイラーはSootを使用します。これは、前回調べたときに、元のJavaコードを再構築するのに非常に野心的でした。私はあなたの例を試していませんが、見てみたいと思うかもしれません。http://www.sable.mcgill.ca/dava/

于 2010-05-15T15:40:51.887 に答える
3

Procyonは、オーバーロードされたメソッド呼び出しを正しく処理する必要があります。Krakatauと同様に、Procyonは最初に、ターゲットメソッドと完全に一致しないすべてのメソッド引数にキャストを挿入します。ただし、これらのほとんどは、冗長なキャストを識別して排除する逆コンパイルの後のフェーズで削除されます。Procyonは、呼び出しが別のメソッドにバインドされないことを確認できる場合にのみ、呼び出し引数のキャストを削除します。たとえば.class、メソッドの宣言を解決できない場合、どのオーバーロードが競合する可能性があるかを知る方法がないため、キャストを削除しようとはしません。

于 2014-03-20T18:10:06.510 に答える
1

以前の回答に追加する:2015年3月現在の最新の逆コンパイラーのリストは次のとおりです。

  • プロキオン
  • CFR
  • JD
  • ファーンフラワー

それらはすべて、オーバーロードされたメソッドをサポートしています。

上記の逆コンパイラをオンラインでテストできます。インストールは不要で、知識に基づいて独自に選択できます。クラウド内のJavaデコンパイラー: http ://www.javadecompilers.com/

于 2015-03-20T04:24:55.943 に答える