Problema ao fazer reversa de .class para .java

Olá Galera, blz?

Seguinte, estou com uma aplicação aqui onde só tenho arquivos .class e preciso gerar os .java para adicionar novas features nesse sistema. Dando uma procurada na net, axei vários programas que fazem essa reversa, dentre eles o DJ Java Decompiler, o JAD, o Cavaj(que roda com jad por baixo), o JD-GUI, entre outros. Consegui realizar a reversa, porém a diferença entre os .java gerados por estas ferramentas me assustou. Comparando alguns .java gerados pelo JAD e pelo JD-GUI, percebi que no .java gerado pelo jd-gui, ele colocou algumas anotações de Spring que existem no projeto, coisa que o jad desconsiderou, nao colocando nem as linhas de import. Porém esse jd-gui colocou a mais uns erros no código-fonte, como por exemplo uns comando break sem sentido, umas variáveis que nem existem, etc…

Depois dessa análise, fiquei meio na dúvida se posso confiar no código gerado por estas ferramentas. Vocês já passaram por esta situação? Vcs indicam alguma outra ferramenta mais confiável do q estas que eu mencionei? Ou será q fiz algo de errado?

Agradeço a ajuda pessoal :smiley:

[]'sss!!!

Normalmente, você não consegue reverter os nomes das variáveis e os comentários.

Não dá pra confiar num codigo desses 100%, mas dá pra ter uma base.

Rapaz confiar 100% eu acho q nao da. Existe classes que o jad decompila bomzinho, eu ja fiz muito isso, alterei o codigo e recompilei, e sem problemas. Quanto aos break sem sentido que vc fala, isso normalmente acontece quando a versao que o decompiler esta tentando decompilar é diferente da versao de compilacao da classe, ai ele desentende o codigo. Tem que verificar as major e minor version e o que o seu decompiler aceita. Veja tbm a versao do class.

A descompilação tem os seguintes problemas:

  • Certos arquivos .class são gerados de tal maneira (com obfuscatores de código, por exemplo) que os descompiladores ficam “atrapalhados” quando tentam descompilar o código;
  • O compilador javac não grava nos arquivos .class várias informações (como nomes das variáveis locais e localização das linhas do código) se você passar os parâmetros adequados);
  • Finalmente, algumas otimizações do javac podem realmente gerar código que é muito difícil de retornar ao original.

Pense num descompilador como se fosse aquela ferramenta de tradução do Google ou do Babelfish. Ela faz o que é possível, mas não consegue fazer 100% perfeito.

A compilação é uma via de mão única. É um processo irreversível. Muita coisa se perde durante a compilação.

O que os descompiladores TENTAM fazer é recuperar algo que seja o mais parecido possível com o código-fonte original. Mas, como há coisas que se perdem, não há descompilação perfeita.

Uma coisa que interfere bastante são as otimizações que o compilador faz. Por vezes o compilador pode eliminar código que ele detecta que não é alcançável. Ele pode reutilizar variáveis locais. Ele pode transformar um for em um while ou em um do-while ou vice-versa. Ele pode inverter condições em ifs e trocar o bloco “then”* pelo bloco “else” para melhorar o desempenho. Ele também vai a otimizar concatenações de Strings e expressões matemáticas. Às vezes o copilador pode inserir instruções break, continue ou return em lugares onde não haviam se ele achar que isso pode melhorar o desempenho sem mudar o comportamento do código.

Por vezes o compilador também criará atributos, métodos ou construtores ocultos (chamados de sintéticos). Um exemplo de atributo oculto é a referência que toda classe interna não-static tem para a classe externa. Retorno covariante é implementado com o uso de alguns métodos sintéticos sobrecarregados.

O compilador também perde o nome de variáveis locais e de atributos. As annotations de variáveis locais são perdidas também. Boa parte dos generics é perdida por causa do type-erasure. Algumas poucas annotations de métodos, construtores, atributos e classes também são perdidas (aquelas que não tem @Retention(RetentionPolicy.RUNTIME) ou @Retention(RetentionPolicy.CLASS)).

Comentários (inclusive javadocs), indentação e formatação do código obviamente são perdidos.

O compilador também explora algumas vantagens que são permitidas pela máquina virtual mas não são pela linguagem. Por exemplo, a JVM permite que haja dois ou mais métodos com o mesmo nome e os mesmos parâmetros, mas a linguagem java não (para a sobrecarga ocorrer, os parâmetros tem que variar). Outra complicação é que a linguagem exige que a chamada ao construtor da superclasse seja a primeira instrução de um construtor, mas a JVM não exige isso.

Daí, os descompiladores burros simplesmente convertem o que o compilador fez direto para a linguagem (o que as vezes resulta em um código muito feio e nem sempre compilável). Descompiladores mais inteligentes tentam desfazer algumas otimizações e/ou maluquices que os compiladores criam. Por fim, há diversos tipos de compiladores diferentes que geram arquivos .class diferentes a partir de um mesmo arquivo .java, daí alguns descompiladores funcionam melhor com certos compiladores do que com outros.

  • ok, java não tem uma palavra chave “then”. Aqui me refiro ao bloco logo após ao “)” do if.

EDIT: Como dito pelo thingol, ainda há ofuscadores de código. Existem ferramentas (às vezes embutidas dentro dos compiladores) que tentam dificultar ao máximo o trabalho de descompiladores criando uma bagunça bem grande no .class.

Opa,

entendi os pontos que vcs levantaram e concordo com eles.

dessas ferramentas q eu enumerei, qual delas vcs julgam que seja a mais “confiável” em termos de conseguir decompilar o código ficando mais próximo do original?

  • JAD
  • DJ Java Decompiler
  • JD-GUI
  • ou CAVAJ???

Use todas, e veja qual é que cometeu menos erros para a classe que você precisa descompilar.
Não dá para lhe sugerir uma coisa do tipo “use X que ele funciona 100%”. Nenhum deles funciona 100%; talvez um que seja ruim na maior parte das vezes consiga descompilar bem uma classe que os outros não conseguem descompilar.
Você não citou o Jode ( http://jode.sourceforge.net ) - ele é 100% Java, mas está um pouco defasado :stuck_out_tongue:

victorwss,

mto das coisas que vc falou eu vi aki na prática, como chamada aos construtores das classes pai não serem a primeira linha, etc…valeu pelos conceitos explicados.

thingol,

valeu por indicar o Jode, porém como vc disse ele está defasado, nao tem suporte a Generics, nem varargs, etc…então axo q nao vai me ajudar mto…mas valeu mesmo assim!!!

Bom, jah vi o problemão que toh na mão aki neh hehehehe

O jeito é vestir a camisa e começar a arrumar as coisas.

Valeu ae pessoal por toda a ajuda.

Abraços!!!