1 / 36

Manipulação de Bytecodes Java

Manipulação de Bytecodes Java. Giuliano Mega. Introdução. O que é bytecode ? Código intermediário Semelhante aos códigos de montagem ( assembly ) Byte-code – opcodes de 1 byte Processadores virtuais (Virtual Machines) Quem usa? Java (JVM), Smalltalk (Slang), .NET (CLR). Introdução.

lilly
Download Presentation

Manipulação de Bytecodes Java

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Manipulação de Bytecodes Java Giuliano Mega

  2. Introdução • O que é bytecode? • Código intermediário • Semelhante aos códigos de montagem (assembly) • Byte-code – opcodes de 1 byte • Processadores virtuais (Virtual Machines) • Quem usa? • Java (JVM), Smalltalk (Slang), .NET (CLR)

  3. Introdução • Assuntos em pauta • Por que? • Reflexão • Como? • JVM • Bytecodes • Técnicas de compilação • Arcabouços • Suposição • Você conhece Java • Você sabe o que é um Class Loader

  4. Reflexão Computacional • Sistemas computacionais • Sistema de computador que responde perguntas ou dá apoio a certas ações sobre algum domínio • Sistema representa o seu domínio por meio de estruturas de dados • Representação causalmente conexa

  5. Reflexão Computacional (cont.) • Meta-sistema • Domínio = outro sistema. • Sistema-objeto. • Sistema reflexivo • Meta-sistema causalmente conexo cujo sistema-objeto é ele próprio. • Conseqüência • Pode modificar aspectos de sua execução como efeito dela mesma.

  6. Arquiteturas Reflexivas • Linguagem dá acesso a estruturas que modificam aspectos da interpretação da linguagem. • Interpretadores metacirculares e variantes • Forma muito explorada de implementação; • poderosa e garantida; • conexão causal garantida pela circularidade. programa interpretador

  7. Arquiteturas Reflexivas (cont.) • Reflexão [1] • Ad hoc • Facilidades providas pela linguagem • Arquitetura reflexiva: • Reconhece reflexão como conceito; • provê meios para fazê-la. • Finalidade aberta (open-ended). • Alguns exemplos: • 3-LISP,BROWN (funcionais) • META-PROLOG, FOL (lógicas) • TEIRESIAS, SOAR (regras) • 3-KRS, SuperEgo (OO) • Prá que que serve afinal?

  8. Reflexão - aplicações • Aplicações • depuração [1]; • prog. concorrente [2]; • backtracking [3]; • futures [4]; • AOP [5]; • etc. • Tudo isso no nível da linguagem • Sem extensões sinistrasao interpretador

  9. Reflexão Java • Afinal, Java é “reflexiva”? • Não conta com uma arquitetura reflexiva. • Segunda categoria • Ausência de meta-nível claro • Introspecção confusa • Limitada • Class loaders • Proxies dinâmicos (JDK 1.3) • Justificativa: desempenho, type-safety [6].

  10. Reflexão Java (cont.) • Programadores Java também precisam de reflexão • logging, estatísticas, tracing, depuração, persistência, AOP... • Reflexão comportamental/estrutural • Proxies dinâmicos • Factories • Não-ortogonais • Aplicações já prontas – difícil.

  11. Reflexão Java (cont.) • “Reflexão” em tempo de compilação (Open Java [7] e cia.) • Não é reflexão, é metaprogramação. • Reflexão em tempo de carga. • Class loaders • Portável entre JVMs • Dizem que é reflexão estrutural • Opinião pessoal: forçada de barra • Formas desajeitadas e não-portáveis de reflexão comportamental/estrutural pela JVMTI (Sun). • Java e adaptação não combinam. • Flexibilidade => adaptação [8].

  12. Manipulação em Tempo de Carga • Forma mais comum e aceita • Portável • Não requer código fonte • “Fácil” e “eficiente” class SRLoader extends ClassLoader { public Class loadClass(String name) { byte[] bytecode = readClassFile(name); <mexa no bytecode o quanto quiser> return resolveClass(defineClass(bytecode)); } }

  13. JVM – formato das classes Formato de classes Java [9]

  14. JVM – básico • JVM é um processador virtual • pilhas, “registradores” • Preocupação com segurança • verificação • opcodes tipados (tipos primitivos)

  15. JVM - A linguagem de montagem • Um pequeno exemplo: • Estáticos: • Tamanho máximo da pilha • Número de variáveis locais (slots)

  16. Manipulação Revisitada • Manipular classes: • Complexo • Muitas dependências • Classe = array de bytes • Necessário interpretar os dados • Arcabouços (BCEL e muitos outros):

  17. Arcabouços de Manipulação • Forma OO de representar/manipular o bytecode • Variam em grau de abstração, tamanho, desempenho... • ByteCode Engineering Library* (BCEL) [10] • ASM [11] • Java Assistant* (Javassist)[12] • Code Generation LIBrary (CGLIB) • SERP • JOIE • etc.

  18. O Java Assistant (Javassist) • Nosso foco: manipulação de alto nível • Intuitivo • Fácil de usar • Dificilmente produz código inválido • Exemplo: • Medir desempenho (interceptadores): private String buildString(int length) { String result = ""; for (int i = 0; i < length; i++){ result += (char)(i%26 + 'a'); } return result; }

  19. Javassist (cont.) • Desempenho • Class Loader • O Javassist já provê um esqueleto • javassist.Loader extends java.lang.ClassLoader • Você só escreve os ganchos • interface javassist.Translator private String buildString(int length) { long start = System.currentTimeMillis(); String result = ""; for (int i = 0; i < length; i++) { result += (char)(i%26 + 'a'); } System.out.println("Call to buildString took " + (System.currentTimeMillis()-start) + " ms."); return result; }

  20. Javassist (cont.) • Translator • Restrições • variáveis locais (lembre-se do bytecode...) • como faço para implementar o exemplo? • “expressão idiomática Javassist” prá isso publicinterface Translator { publicvoid start(ClassPool pool) throws NotFoundException, CannotCompileException; publicvoid onLoad(ClassPool pool, String classname) throws NotFoundException, CannotCompileException; }

  21. Javassist (cont.) CtClass clas = pool.get(cname); CtMethod[] meths = clas.getDeclaredMethods(); for (int i = 0; i < meths.length; i++) { CtMethod mold = methds[i]; String nname = mname+"$impl"; /* 1) Muda o nome do método e duplica com o nome antigo */ mold.setName(nname); CtMethod mnew = CtNewMethod.copy(mold, mname, clas, null); /* 2) Cria o embrulho-cronômetro para o método original */ String type = mold.getReturnType().getName(); StringBuffer body = new StringBuffer(); body.append("{\nlong start = System.currentTimeMillis();\n"); if (!"void".equals(type)) { body.append(type + " result = "); } body.append(nname + "($$);\n"); ... /* 3) Substitui o código do método embrulhado */ mnew.setBody(body.toString()); clas.addMethod(mnew); }

  22. Javassist (cont.) • A técnica envolve ainda um “lançador” • Em geral provido pelo arcabouço • Limitações • Não é muito flexível • Classes internas e anônimas • Código original vai parar em outro método • Lento • Modificações internas • Introspecção limitada • Proposta não é essa • Tem uma API para bytecodes.

  23. A ByteCode Engineering Library (BCEL) • Transforma a classe Java num grafo • ByteCodes orientados a objeto • Poderoso • Mais “intuitivo” que o Javassist • Prá quem conhece bytecodes • Mais rápido que o Javassist • Exemplo: • Instrumentar todos os métodos Run de todos os Runnables

  24. BCEL (cont.) public JavaClass modifyClass(JavaClass jc) { /* 1) Testa se a classe é instância de Runnable */ JavaClass runnableIntf = Repository.lookupClass("java.lang.Runnable"); if(!jc.instanceOf(runnableIntf)) return jc; Method [] methods = jc.getMethods(); int i = 0; for(i = 0; i < methods.length; i++){ if(methods[i].getName().equals("run")) break; } /* 2) Cria as versões maleáveis (de-serializa) e as modifica */ ClassGen newClass = new ClassGen(jc); ConstantPoolGen cg = newClass.getConstantPool(); MethodGen mg = new MethodGen(m, newClass.getClassName(), cg); newClass.removeMethod(methods[i]); ... /* 3) Calcula dados estáticos, re-serializa o bytecode */ mg.setMaxStack(); mg.setMaxLocals(); newClass.addMethod(mg.getMethod()); return newClass.getJavaClass(); }

  25. BCEL (cont.) InstructionList il = new InstructionList(); InstructionFactory iFactory = new InstructionFactory(nc); il.append(iFactory.createFieldAccess("java.lang.System", "out", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC)); il.append(new PUSH(cg, "Método \"run\" chamado na classe " + jc.getName()); il.append(iFactory.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); InstructionList old_il = mg.getInstructionList(); InstructionHandle [] handles = old_il.getInstructionHandles(); old_il.insert(handles[0], il); mg.setInstructionList(old_il);

  26. BCEL (cont.) • Problemas • Ainda é lento; • pode ser muito complexo; • manipulação direta de bytecodes; • muito fácil gerar código inválido.

  27. ASM • Visitor pattern • Não seria/de-seria o grafo • Composição de visitors • Substituição • Muito rápido • 700% mais rápido que o BCEL • 1100% mais rápido que o SERP • Compacto • 25 kb vs. 350 kb do BCEL • Lembra um pull parser prá XML. • Não alivia muito em manipulações complexas.

  28. Verificação de Bytecode • O que há de errado com este (pseudo) bytecode? 00 aload_0 01 invokevirtual “MyClass#test()” 02 ifne 05 03 aload_0 04 invokevirtual “MyClass#test()” 05 return Rode isso e...: java.lang.VerifyError: stack sizes differ (1 != 0).

  29. Verificação de Bytecode (cont.) • Esse código não passa pelo verificador (pág. 12) • Verificador • Algoritmo de análise de fluxo • Prova um teorema ou arruma um contra-exemplo • Problemas de decidibildade • Restrições mais fortes do que o necessário. • Rejeita código “válido”.

  30. Verificação de Bytecode (cont.) 00 aload_0 01 invokevirtual “MyClass.test()” 02 ifne 05 03 aload_0 04 invokevirtual “MyClass.test()” 05 return • Análise de tipos + stack merging = código seguro + chatice. • Merging em laços.

  31. Verificação de Bytecode (cont.) • Compilador “burla” o verificador • Sempre produz código válido; • equivalente ao código-fonte; • nós não temos o código-fonte. • Transformações difíceis • Armadilhas (traps); • implementadas com subrotinas.

  32. Problemas Adicionais • Class Loader que instrumenta: • Tem que definir a classe; • saber o que “deixar passar” (i.e. java.lang.*); • getSystemClassloader(); • a opção -Dendorsed.dirs=...; • Limitação: classes de sistema.

  33. Conclusão • Java: reflexão deficitária. • Desempenho. • Segurança. • Manipulação: • Reflexão estrutural limitada. • Manipulação em tempo de carga: • em acordo com a filosofia Java. • Arcabouços: • facilitam a tarefa. • compromisso entre flexibilidade, complexidade e desempenho.

  34. Referências: [1] P. Maes. Concepts and Experiments in Computational Reflection. In Proceedings of the OOPSLA’87. pages 147-155. Orlando, Florida. [2] B. Foote. Objects, Reflection and Open Languages. In Proceedings of the 1992 ECOOP Workshop on Object-Oriented reflection and Meta-Level Architectures. Utrecht, Netherlands [3] W. R. LaLonde and M. V. Gulik. Building a Backtracking Facility in Smalltalk Without Kernel Support. In Proceedings of the OOPSLA’88. pages 105-122. San Diego, California. [4] B. Foote and R. Johnson. Reflective Facilities in Smalltalk-80. In Proceedings of the OOPSLA’89. pages 327-335. New Orleans, Louisiana. [5] S. Kojarski and D. Lorentz. AOP as a First-class reflective mechanism. In Companion to the OOPSLA’04. pages 216 – 217. Vancouver, Canada. [6] S. Liang and G. Bracha. Dynamic Class Loading in the Java Virtual Machine. In Proceedings of the OOPSLA’98. pages 36-44. Vancouver, Canada. [7] M. Tsubori, S. Chiba et. al. OpenJava: A Class-based Macro System for Java. In Reflection and Software Engineering, LNCS 1826, Springer-Verlag, 2000. /15

  35. Referências (cont.) [8] B. Foote. Class Warfare: Classes vs. Prototypes. In Proceedings of the OOPSLA’89 Workshop on Objects without Classes, New Orleans, LA. [9] T. Lindholm and F. Yellin. The Java Virtual Machine Specification. Addison-Wesley, 2nd edition, 1999. [10] BCEL website. http://apache.jakarta.org/bcel. [june 9, 2005] [11] E. Bruneton, R. Lenglet and T. Coupaye. ASM: a code manipulation tool to implement adaptable systems. In ACM SIGOPS Adaptable and extensible component systems. 2002, Grenoble, France. [12] Javassist website. http://www.csg.is.titech.ac.jp/~chiba/javassist [june 8, 2005]

  36. Dúvidas?

More Related