Ajuda com ASM

Estou querendo usar o ASM para poder ler uma classe já compilada, mas não estou conseguindo nem sair do “Hello World” :? , alguém poderia ajudar?

Cara… tem muita coisa pra voce aprender como resposta para a pergunta “poderiam me ajudar?”.

Seja mais especifico.

Como começar no ASM? Você teria algum tutorial bem básico? Por exemplo de como ler um código a partir de um .class?
Tentei usar o javassist para fazer isso, mas acho que com ele não dá.

Acho que é melhor começar pelo FAQ - ele indica que é bom você rodar o ASMifier pelo menos para entender o que o ASM requer, e é interessante você ver a saída do programa.

http://asm.ow2.org/doc/faq.html

Também existe um plugin pro eclipse que facilita usar o ASMifier.

E qual sua intenção em usar ASM?

Quer ver o código fonte ou como funciona os .class?

Atenção: o ASM não é adequado para você "descompilar" um programa. Ele é muito bom, por exemplo, para você criar ou modificar uma classe (alguns frameworks de AOP usam o ASM, se não me engano).

Se você quer simplesmente "desassemblar" um programa (ou seja, .class -> bytecodes), use o javap mesmo.

O que você quer fazer com o ASM?

Eu quero alterar partes do código. Por exemplo pegar a linha de um determinado método e comentar a mesma e ai incluir uma outra linha.
E também queria saber se eu posso procurar dentro do código por uma determinada palavra. Por exemplo se find(test.a()).

entao… use o ASMifier comparando a classe compilada e a classe que voce quer como resultado.

Ele vai te mostrar o código necessario para alterar.

[quote=Jedi_FeniX]Eu quero alterar partes do código. Por exemplo pegar a linha de um determinado método e comentar a mesma e ai incluir uma outra linha.
E também queria saber se eu posso procurar dentro do código por uma determinada palavra. Por exemplo se find(test.a()).[/quote]

Pegar uma linha e comentar, e incluir outra linha? O ASM não é indicado para isso (já que trabalha com .class, não com .java). O correto, no seu caso, é trabalhar com alguma API de “Abstract Syntax Tree”, tais como as que o Eclipse e o NetBeans usam para analisar e compilar programas.

Teria alguma API para indicar thingol?
Lembrando que eu só tenho os .class.

Se você só tem o .class aí fica um pouco mais difícil, já que você só tem os bytecodes.

Você não tem em bytecodes o conceito de “editar ou comentar uma linha”, que é coisa de código java, não de bytecodes.

Talvez, dependendo do que você quer, você tenha de descompilar o código, arrumar o código descompilado manualmente, e então recompilar.

O que você poderia fazer com o ASM é uma ferramenta que pegaria um .class e produziria outro .class, mas com constantes strings modificadas (por exemplo). Digamos que o .class original tivesse uma string assim:

public static final String AUTOR = "José Aparecido";

você poderia fazer algo que gerasse um .class com algo semelhante a:

public static final String AUTOR = "Maria das Dores";

O que não dá para fazer em ASM de forma muito trivial é algo assim:

// Original
for (int i = 1; i <= 10; ++i) {
    System.out.println (i);
}
// Alterado
while (i < 100) {
    System.out.printf ("%d\n", i++); 
}

Que tipo de modificação você quer fazer? Diga que talvez a gente consiga indicar uma solução.

É só tenho os .class.
Estava tendo fazer isso com o javassist, nele eu consigo alterar o bytecode, mas só incluir código, não consigo apagar nada.
Abaixo tem um exemplo para vocês entenderem melhor:

Exemplo:

Um usuário faz um upload para myApp.
E ai myApp abre o . jar, lê o .class e faz as alterações necessárias no .class.

Quais são as “alterações necessárias”?

A alteração que quero fazer é deste tipo.

A minha aplicação abre o .class e modifica a chamada de um método.

Original:

if(a.equals(b)){ b.methodA(); }

Modificado:

if(a.equals(b)){ b.methodB(); }

Só isso? Se o método tiver exatamente a mesma assinatura, então você só precisa implementar visitMethodInsn; você troca a chamada a methodA por uma chamada a methodB.

Se tiver assinatura diferente (por exemplo, um parâmetro a mais), então é mais complicado porque você precisa remover ou adicionar código, e isso não é trivial.

Bom, como o meu tempo é pequeno tem como “fazer” a assinatura do método ser a mesma para que fique mais fácil.
Você teria algum exemplo de como eu posso fazer esta modificação? E outra coisa eu teria que varrer o .class inteiro atrás do methodA().

Você entendeu como é que se usa o ASM?
Ele usa o pattern “visitor”.
Então você carrega o .class com o ASM e então o ASM chama uma classe que você define; para cada classe de bytecodes (como invokespecial, invokevirtual etc.) existe um método determinado, que você pode sobrecarregar ou não.
Sobrecarregar esse método é definir o que fazer quando você encontrar a tal instrução.
No seu caso, para todas as instruções, exceto visitMethodInsn, você simplesmente deixa a instrução do jeito que está. Mas visitMethodInsn deve mudar a chamada de methodA para methodB.

Aí que está eu ainda não entendi muito bem, fui no site do ASM, mas achei complicada a explicação deles.
Você teria algum outro material para indicar? Baixei do site do ASM alguns exemplos, mas mesmo assim está difícil de entender.
Gostaria de agradecer a ajuda que vc está dando!!! Valeu!!! :thumbup: