IntroducciónJVM bytecode es el formato binario de código ejecutable por la máquina virtual de java.Algo así como el famoso lenguaje máquina "assembler", pero para la VM de java. Podemos ver el bytecode al abrir un archivo .class Por supuesto va a ser completamente inentendible. Entonces, para esto podemos usar un plugin de eclipse como este. OpCode's e InstruccionesEste lenguaje (porque en definitiva es un lenguaje, si bien de bajo nivel y binario, es un lenguaje) consta básicamente de instrucciones, cada instrucción tiene un código que la identifica llamado opcode y opcionalmente parámetros.El opcode se expresa en forma de bytes, pero existe una convención de nombres cortos para poder hacer más legible el bytecode. Entonces, veamos un ejemplo. El siguiente código que suma dos valores: public void sumar() { int a = 2; int b = 3; int resultado = a + b; } Se traduce al siguiente bytecode: iconst_2 istore 1 iconst_3 istore 2 iload 1 i load 2 iadd istore 3 return maxstack 2 maxlocals 4 Acá vemos un par de cosas. Cada linea tiene una instrucción con su respectivo opcode en formato "legible".
Stack-Oriented modelComo vimos en el ejemplo anterior aparece la idea de stack. Esto es importante de al menos mencionar, la JVM y su bytecode está diseñada en base a un stack y no de registros. Como es por ejemplo el modelo de assembler.Este modelo está relacionado con la idea del modelo de objetos (llamadas a métodos). En realidad es un tema de bastante bajo nivel, pero digamos que esto le permite a la VM poder ejecutar más eficientemente en procesadores que no tienen un conjunto de registros extendidos. A nivel práctico esto quiere decir que la mayoría de las instrucciones operan sobre el stack, por ejemplo en nuestro caso la suma obtiene los operandos popeandolos del stack. Quiere decir que nos vamos a hartar de ver manipulación del stack cuando veamos bytecodes. Esto hace al bytecode un poco más dificil de leer y más verborrágico. Hola Mundo (invokevirtual)Veamos como se traduce el famoso hola mundo de esto:A bytecode: getstatic java/lang/System.out : Ljava/io/PrintStream; ldc "Hello, world!" invokevirtual java/io/PrintStream.println(Ljava/lang/String;)V return Donde:
Invoke*Existen varios opcode para la invocación de métodos:
invokevirtualComo ya vimos en el ejemplo de "Hola Mundo", el invokevirtual se utiliza para invocar métodos haciéndo uso del mecanismo de dispatching dinámico para localizar y ejecutar la implementación del método de acuerdo a la clase concreta del receptor.Este dispatching se hace sobre la jerarquía de la clase. Algo importante a tener en cuenta es que esta instrucción se utiliza para invocar métodos de instancia declarados en clases y no en interfaces. Para este último caso existe la instrucción invokeinterface. invokeinterfaceBastante similar al invokevirtual se utiliza para invocar un método, declarado en una interface. De nuevo se ejecutará el dispatching dinámico sobre el receptor.Veamos un ejemplo:
invokespecialSe utiliza para invocar un método puntual, sin realizar dispatching dinámico. Es decir para invocar métodos "no-virtuales". En java decimos que todos los métodos son virtuales por default, porque generalmente el bytecode que escribimos se traduce a instrucciones invokevirtual y/o invokeinterface. En otros lenguajes como C# se da lo contrario y hay que especificar qué métodos queremos que sean virtuales.En fin, volviendo a java, el tema es que hay ciertas invocaciones especiales donde no hay dispatching. Estos son los casos:
invokestaticSe utiliza para invocar métodos static. Obviamente no hay dispatching.invokedynamicEs una instrucción nueva en la JVM versión 7, que muchos lenguajes están esperando, porque permitirá invocar un método en forma dinámica, es decir, con dispatching, pero sin necesidad de especificar la clase que lo declara y la firma del método.Esto va a dar el soporte necesario para lenguajes dinámicos que hoy en día igualmente se construyen sobre la JVM pero con muchas limitaciones o con "truquitos" para evadir la naturaleza estática y los checkeos de java. Muchas veces esto causa un pérdida considerable de performance de estos lenguajes o consumo de memoria. Referencias
|
Tecnologías >