C'è qualche Decompiler Java che può correttamente decompilare chiamate ai metodi di overload? [chiuso]

StackOverflow https://stackoverflow.com/questions/2840183

  •  27-09-2019
  •  | 
  •  

Domanda

Si consideri questo (IMHO semplice) esempio:

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 + " ");
    }
}

compilarlo con il livello di origine / destinazione 1.1 senza informazioni di debug (vale a dire nessuna informazione variabile locale dovrebbe essere presente) e cercare di decompilare esso. Ho provato Jad, JD-GUI e Fernflower, e tutti loro ho almeno una parte del torto chiamata (i. E. Il programma stampato "Sbagliato!" Almeno una volta)

Non c'è proprio nessuna decompilatore Java che possono dedurre i calchi giusti in modo che non chiamerà il sovraccarico di sbagliato?

Modifica Livello obiettivo 1.1 in modo che non v'è niente di tutto questo java6-specifici rapida convalida informazioni presenti. Questo potrebbe dare il decompilatore un indizio che s1 è stato dichiarato come Object e non come String. Decompilers dovrebbero essere in grado di decompilare il codice anche senza questa informazione (non necessariamente ottenere il tipo variabile originale, ma mostrano lo stesso comportamento), soprattutto perché molti obfuscators striscia esso pure.

Cosa Decompilers sbagliato ottenuto:

  • hanno perso il cast al (Object) nella prima chiamata.
  • Si dedurre il tipo di s1 essere String, ma ha dimenticato di aggiungere un cast per la chiamata a doPrint (in modo che la versione stringa è chiamata invece della versione Object).
  • Un uno scadente (non ho ancora quotata) deduce anche il tipo di s2 essere String, causando il codice uncompilable.

In ogni caso, questo codice non chiama mai il sovraccarico String, ma il codice decompilato ha fatto.

È stato utile?

Soluzione

Krakatau gestisce correttamente tutti i metodi di overload, anche i metodi di overload sui tipi primitivi, che la maggior parte dei decompilatori sbagliare. Getta sempre argomenti al tipo esatto del metodo chiamato, in modo che il codice può essere più ingombra del necessario, ma almeno è corretto.

Disclosure:. Io sono l'autore di Krakatau

Altri suggerimenti

Ciao mihi,

scusate per il ritardo di risposta. Sto copiando la mia risposta da http://www.reversed-java.com/ fernflower / forum? threadfolder = 2_DE

Il tuo problema è in realtà uno ben noto. Vediamo:

1) bytecode pura non contiene alcuna informazione sul tipo di variabili oggetto, così nel primo s1 pass e s2 sono dichiarati come oggetto.

2) Decompiler è difficile cercare di assegnare il tipo migliore possibile ciascuna variabile (= "stretta principio tipo" implementato in Fernflower). Quindi, S1 e S2 sono correttamente identificati come esempi di stringa.

3) Invocazione di doPrint ci danno un link al metodo corretto
private static doPrint void (Object S1)

4) Tutto OK finora, giusto? Ora abbiamo ottenuto una variabile String s1 passato a una funzione, che si aspetta un oggetto. Abbiamo bisogno di lanciarla? Non in quanto tale, si potrebbe pensare, come oggetto è un super-tipo di stringa. E tuttavia lo facciamo - perché c'è un'altra funzione all'interno della stessa classe con lo stesso nome e una firma parametro diverso. Quindi abbiamo bisogno di analizzare tutta la classe per scoprire, se un cast è necessario o no.

5) In generale, significa che dobbiamo analizzare tutte le classi di riferimento in tutte le librerie tra cui il runtime Java. Un enorme carico di lavoro! In effetti, questa funzionalità è stata implementata in qualche versione alpha di Fernflower, ma non hanno reso nella produzione ma a causa di prestazioni e rigore della memoria. Altri decompilatori menzionate mancano di questa capacità di progettazione.

Spero di aver chiarito le cose un po ':)

Il plugin JadClipse Eclipse per la decompilazione fornisce anche il decompilatore JODE, che si consiglia di provare. Io lo uso quando Jad arrende.

Anche il decompilatore Dava utilizza Fuliggine che - ultima volta che ho guardato - era molto ambizioso nel ricostruire il codice originale Java. Non ho provato con il tuo esempio, ma si consiglia di dare un'occhiata. http://www.sable.mcgill.ca/dava/

Procyon dovrebbe gestire correttamente invocazioni metodo di overload. Come Krakatau, Procyon inserisce inizialmente stampi per ogni argomento metodo che non corrisponde esattamente il metodo di destinazione. Tuttavia, la maggior parte di questi verranno rimossi in una fase successiva di decompilation che identifica ed elimina ridondanti calchi. Procyon rimuoverà solo calchi su argomenti di chiamata se si può verificare che così facendo non comporterà il legame con un metodo diverso chiamata. Ad esempio, se il .class dichiarando il metodo non può essere risolto, esso non tentare di rimuovere i calchi a tutti, perché non ha modo di sapere ciò che sovraccarica il conflitto potrebbe.

L'aggiunta alle risposte precedenti: Ecco un elenco dei decompilatori moderni a partire da marzo 2015:

  • Procyon
  • CFR
  • JD
  • Fernflower

tutti supportano metodi di overload.

E 'possibile testare sopra decompilers menzione on-line, non richiede installazione e fare la propria scelta istruiti. Java decompilatori in the cloud: http://www.javadecompilers.com/

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top