Existe algum decompilador Java que possa descompilar corretamente chamadas para métodos sobrecarregados? [fechado

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

  •  27-09-2019
  •  | 
  •  

Pergunta

Considere este exemplo (IMHO simples):

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

Compile -o com o nível de origem/destino 1.1 sem informações de depuração (ou seja, nenhuma informação de variável local deve estar presente) e tente descompilá -las. Eu tentei Jad, JD-Gui e Fernflower, e todos eles conseguiram pelo menos uma das chamadas erradas (ou seja, o programa impresso "errado!" Pelo menos uma vez)

Realmente não existe um decompilador Java que possa inferir os elencos certos para que não chama a sobrecarga errada?

Editar: Nível de alvo 1.1 para que não exista nenhuma dessas informações de validação rápida específica de Java6 presentes. Isso pode dar ao decompilador uma pista de que S1 foi declarado como Object e não como String. Os decompiladores devem ser capazes de descompilar o código mesmo sem essas informações (não necessariamente obter o tipo de variável original, mas mostrar o mesmo comportamento), especialmente porque muitos ofuscadores também a retiram.

O que os decompiladores erraram:

  • Eles perderam o elenco para (Object) Na primeira chamada.
  • Eles inferiram o tipo de s1 ser String, mas esqueci de adicionar um elenco à chamada para doPrint (para que a versão da string seja chamada em vez da versão do objeto).
  • Um péssimo (eu nem listei) mesmo infecta o tipo de s2 para ser string, causando código não compilável.

De qualquer forma, este código nunca chama o String Sobrecarga, mas o código descompilado fez.

Foi útil?

Solução

Krakatau Lida corretamente todos os métodos sobrecarregados, mesmo os métodos sobrecarregados em tipos primitivos, que a maioria dos decompiladores erram. Ele sempre lança argumentos para o tipo exato do método chamado, para que o código possa ser mais confuso do que o necessário, mas pelo menos está correto.

Divulgação: Eu sou o autor de Krakatau.

Outras dicas

Hallo Mihi,

Desculpe pela resposta tardia. Estou copiando minha resposta de http://www.reversed-java.com/fernflower/forum?threadfolder=2_de

Seu problema é realmente conhecido. Vamos ver:

1) O bytecode puro não contém nenhuma informação sobre o tipo de variável de objeto; portanto, no primeiro passe S1 e S2 são declarados como objeto.

2) O Decompiler está tentando atribuir o melhor tipo possível a cada variável (= "Princípio do tipo mais estreito" implementado no Fernflower). Portanto, S1 e S2 são corretamente identificados como instâncias de string.

3) A invocação de doprint nos dá um link direto para o método correto
DOPRINT PRIVADA ESTÁTICA VOID (Objeto S1)

4) Tudo bem até agora, certo? Agora, temos uma variável de string S1 passada para uma função, que espera um objeto. Precisamos lançá -lo? Não, como tal, você pensaria, pois o objeto é um super-tipo de string. E, no entanto, fazemos - porque existe outra função na mesma classe com o mesmo nome e uma assinatura de parâmetro diferente. Portanto, precisamos analisar toda a classe para descobrir, se um elenco é necessário ou não.

5) De um modo geral, significa que precisamos analisar todas as classes referenciadas em todas as bibliotecas, incluindo o tempo de execução do Java. Uma enorme carga de trabalho! De fato, esse recurso foi implementado em alguma versão alfa do Fernflower, mas ainda não o fez na produção por causa da penalidade de desempenho e memória. Outros descompiladores mencionados não têm essa habilidade por design.

Espero ter esclarecido um pouco as coisas :)

O plug -in JadClipse Eclipse para descompilar também fornece o decompilador Jode, que você pode querer experimentar. Eu o uso quando Jad desiste.

Além disso, o Dava Decompiler usa fuligem que - da última vez que eu parecia - foi muito ambicioso na reconstrução do código Java original. Eu não tentei com o seu exemplo, mas você pode querer dar uma olhada. http://www.sable.mcgill.ca/dava/

Procyon deve lidar com invocações de método sobrecarregado corretamente. Como Krakatau, o Procyon insere inicialmente elenco para todos os argumentos de métodos que não correspondem exatamente ao método de destino. No entanto, a maioria deles será removida durante uma fase posterior de descompilação que identifica e elimina fundidos redundantes. O Procyon removerá apenas os lançamentos em argumentos de chamada se puder verificar se isso não resultará na ligação de chamadas a um método diferente. Por exemplo, se o .class Declarando o método não pode ser resolvido, ele não tentará remover os elencos, porque não tem como saber quais sobrecarga podem conflitar.

Adicionando às respostas anteriores: Aqui está uma lista de decompiladores modernos em março de 2015:

  • Procyon
  • Cfr
  • JD
  • Fernflower

Todos eles suportam métodos sobrecarregados.

Você pode testar os decompiladores acima mencionados on -line, não é necessária instalação e fazer sua própria escolha educada. Decompiladores de Java na nuvem: http://www.javadecompilers.com/

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top