Gibt es einen Java Decompiler, der Aufrufe zu überladenen Methoden korrekt dekompilieren kann?

8

Betrachten Sie dies (IMHO einfach) Beispiel:

%Vor%

Kompilieren Sie es mit Quell- / Ziel-Ebene 1.1 ohne Debug-Informationen (d. h. keine lokalen Variableninformationen sollten vorhanden sein) und versuchen Sie, es zu dekompilieren. Ich habe versucht Jad, JD-GUI und Fernflower, und alle von ihnen haben mindestens einen der Anruf falsch (d. H. Das Programm gedruckt mindestens einmal "Falsch!")

Gibt es wirklich keinen Java Decompiler, der die richtigen Casts ableiten kann, damit er nicht die falsche Überladung aufruft?

Bearbeiten: Zielstufe 1.1, sodass keine Java6-spezifischen Informationen zur schnellen Validierung vorhanden sind. Das könnte dem Decompiler einen Hinweis geben, dass s1 als Object deklariert wurde und nicht als String . Decompiler sollten in der Lage sein, den Code auch ohne diese Informationen zu dekompilieren (nicht unbedingt den ursprünglichen Variablentyp zu erhalten, sondern das gleiche Verhalten zu zeigen), besonders da viele Obfuscatoren ihn ebenfalls entfernen.

Was Decompilers falsch gemacht haben:

  • Sie haben die Besetzung im ersten Aufruf an (Object) verpasst.
  • Sie haben den Typ von s1 als String erkannt, aber vergessen, einen Aufruf zum Aufruf von doPrint hinzuzufügen (so dass die String-Version anstelle der Objekt-Version aufgerufen wird).
  • Ein beschissener (ich habe noch nicht einmal aufgeführt) sagt sogar, dass der Typ von s2 String ist, was nicht kompilierbaren Code verursacht.

In jedem Fall ruft dieser Code nie die String -Überladung auf, aber der dekompilierte Code hat das getan.

    
mihi 15.05.2010, 13:01
quelle

5 Antworten

4

Krakatau behandelt alle überladenen Methoden korrekt, sogar Methoden, die auf primitive Typen überladen sind, was die meisten Decompiler falsch verstehen. Es werden immer Argumente auf den genauen Typ der aufgerufenen Methode angewendet, so dass der Code möglicherweise unübersichtlicher als nötig ist, aber zumindest ist er korrekt.

Offenlegung: Ich bin der Autor von Krakatau.

    
Antimony 10.03.2014, 16:38
quelle
9

Hallo mihi,

Entschuldigung für die späte Antwort. Ich kopiere meine Antwort von Ссылка

Ihr Problem ist eigentlich ein bekanntes Problem. Mal sehen:

1) Reiner Bytecode enthält keine Informationen über den Typ der Objektvariablen, daher werden s1 und s2 im ersten Durchgang als Objekt deklariert.

2) Decompiler bemüht sich, jeder Variablen den bestmöglichen Typ zuzuweisen (= "schmalstes Typsprinzip", implementiert in Fernflower). So werden s1 und s2 korrekt als Instanzen von String identifiziert.

3) Aufruf von doPrint gibt uns einen direkten Link zur richtigen Methode
private static void DoPrint (Objekt s1)

4) Alles in Ordnung soweit, oder? Jetzt haben wir eine String-Variable s1 an eine Funktion übergeben, die ein Object erwartet. Müssen wir es werfen? Nicht als solches würden Sie denken, da Objekt ein Supertyp von String ist. Und dennoch - weil es innerhalb derselben Klasse eine andere Funktion mit demselben Namen und einer anderen Parametersignatur gibt. Also müssen wir die ganze Klasse analysieren, um herauszufinden, ob ein Cast benötigt wird oder nicht.

5) Im Allgemeinen bedeutet dies, dass wir ALLE referenzierten Klassen in ALL-Bibliotheken einschließlich der Java-Laufzeit analysieren müssen. Eine riesige Menge Arbeit! In der Tat wurde dieses Feature in einigen Alpha-Versionen von Fernflower implementiert, hat es aber aufgrund von Performance- und Speicherproblemen noch nicht in die Produktion geschafft. Andere erwähnte Decompiler haben diese Fähigkeit nicht im Design.

Ich hoffe, ich habe die Dinge etwas geklärt:)

    
Stiver 10.06.2010 10:51
quelle
3

Das JadClipse Eclipse-Plugin zum Dekompilieren bietet auch den JODE-Decompiler, den Sie vielleicht ausprobieren möchten. Ich benutze es, wenn Jad aufgibt.

Auch der Dava-Decompiler verwendet Soot, der - beim letzten Mal - sehr ehrgeizig beim Rekonstruieren des ursprünglichen Java-Codes war. Ich habe es nicht mit Ihrem Beispiel versucht, aber Sie möchten vielleicht einen Blick darauf werfen. Ссылка

    
quelle
3

Procyon sollte überladene Methodenaufrufe korrekt behandeln. Wie bei Krakatau fügt Procyon anfänglich für jedes Methodenargument Umwandlungen ein, die nicht genau mit der Zielmethode übereinstimmen. Die meisten davon werden jedoch in einer späteren Phase der Dekompilierung entfernt, die redundante Umwandlungen identifiziert und eliminiert. Procyon wird nur Umwandlungen von Aufrufargumenten entfernen, wenn es sicherstellen kann, dass dies nicht dazu führt, dass die Aufrufbindung an eine andere Methode erfolgt. Wenn beispielsweise .class die Methode nicht deklarieren kann, wird sie nicht versuchen, die Umwandlungen zu entfernen, weil sie nicht wissen kann, welche Überladungen einen Konflikt verursachen könnten.

    
Mike Strobel 20.03.2014 18:10
quelle
2

Zu den vorherigen Antworten hinzufügen: Hier ist eine Liste von modernen Decompilern ab März 2015:

  • Procyon
  • CFR
  • JD
  • Fernblume

ALLE unterstützen überladene Methoden.

Sie können oben genannte Decompiler online testen, keine Installation erforderlich machen und Ihre eigene fundierte Wahl treffen. Java-Decompiler in der Cloud: Ссылка

    
Andrew Rukin 20.03.2015 04:24
quelle

Tags und Links