Código de bytes de Java

Conjunto de instrucciones de la máquina virtual Java

El bytecode de Java es el conjunto de instrucciones de la máquina virtual Java (JVM), el lenguaje en el que se compila Java y otros códigos fuente compatibles con JVM . [1] Cada instrucción está representada por un solo byte , de ahí el nombre bytecode , lo que lo convierte en una forma compacta de datos . [2]

Debido a la naturaleza del bytecode, un programa de bytecode Java se puede ejecutar en cualquier máquina con una JVM compatible; sin el largo proceso de compilación desde el código fuente.

El código de bytes de Java se utiliza en tiempo de ejecución, ya sea interpretado por una JVM o compilado en código de máquina mediante compilación just-in-time (JIT) y se ejecuta como una aplicación nativa.

Como el código de bytes de Java está diseñado para una compatibilidad y seguridad entre plataformas, una aplicación de código de bytes de Java tiende a ejecutarse de manera consistente en varias configuraciones de hardware y software . [3]

Relación con Java

En general, un programador Java no necesita comprender el bytecode de Java ni siquiera conocerlo. Sin embargo, como se sugiere en la revista IBM developerWorks, "comprender el bytecode y qué bytecode es probable que genere un compilador Java ayuda al programador Java de la misma manera que el conocimiento del lenguaje ensamblador ayuda al programador C o C++ ". [4]

Arquitectura del conjunto de instrucciones

El código de bytes comprende varios tipos de instrucciones, incluida la manipulación de datos, la transferencia de control, la creación y manipulación de objetos y la invocación de métodos, todos ellos parte integral del modelo de programación orientada a objetos de Java. [1]

La JVM es a la vez una máquina de pila y una máquina de registros . Cada marco para una llamada de método tiene una "pila de operandos" y una matriz de "variables locales". [5] : 2.6  [2] La pila de operandos se utiliza para los operandos de los cálculos y para recibir el valor de retorno de un método llamado, mientras que las variables locales sirven para el mismo propósito que los registros y también se utilizan para pasar argumentos de método. El tamaño máximo de la pila de operandos y la matriz de variables locales, calculado por el compilador, es parte de los atributos de cada método. [5] : 4.7.3  Cada uno puede tener un tamaño independiente de 0 a 65535 valores, donde cada valor es de 32 bits. longy doublelos tipos, que son de 64 bits, ocupan dos variables locales consecutivas [5] : 2.6.1  (que no necesitan estar alineadas a 64 bits en la matriz de variables locales) o un valor en la pila de operandos (pero se cuentan como dos unidades en la profundidad de la pila). [5] : 2.6.2 

Conjunto de instrucciones

Cada código de bytes se compone de un byte que representa el código de operación , junto con cero o más bytes para los operandos. [5] : 2.11 

De los 256 códigos de operación de bytes de longitud posibles , a partir de 2015 [actualizar], 202 están en uso (~79%), 51 están reservados para uso futuro (~20%) y 3 instrucciones (~1%) están reservadas permanentemente para que las usen las implementaciones de JVM. [5] : 6.2  Dos de estos ( impdep1y impdep2) son para proporcionar trampas para software y hardware específicos de la implementación, respectivamente. El tercero se utiliza para que los depuradores implementen puntos de interrupción.

Las instrucciones se dividen en varios grupos amplios:

  • Cargar y almacenar (por ejemplo aload_0, istore)
  • Aritmética y lógica (por ejemplo ladd, fcmpl)
  • Conversión de tipo (por ejemplo i2b, d2i)
  • Creación y manipulación de objetos ( new, putfield)
  • Gestión de la pila de operandos (por ejemplo swap, dup2)
  • Transferencia de control (por ejemplo ifeq, goto)
  • Invocación y retorno de método (por ejemplo invokespecial, areturn)

También hay algunas instrucciones para una serie de tareas más especializadas, como lanzamiento de excepciones, sincronización, etc.

Muchas instrucciones tienen prefijos y/o sufijos que hacen referencia a los tipos de operandos sobre los que operan. [5] : 2.11.1  Estos son los siguientes:

Prefijo/sufijoTipo de operando
ientero
llargo
scorto
bbyte
cpersonaje
fflotar
ddoble
areferencia

Por ejemplo, iaddsumará dos números enteros, mientras que daddsumará dos números dobles. Las instrucciones const, load, y storetambién pueden tomar un sufijo de la forma , donde n es un número del 0 al 3 para y . El máximo n para difiere según el tipo._nloadstoreconst

Las constinstrucciones insertan un valor del tipo especificado en la pila. Por ejemplo, iconst_5insertará un entero (valor de 32 bits) con el valor 5 en la pila, mientras que dconst_1insertará un doble (valor de punto flotante de 64 bits) con el valor 1 en la pila. También hay un aconst_null, que inserta una nullreferencia. La n para las instrucciones loady storeespecifica el índice en la matriz de variables locales desde donde cargar o donde almacenar. La aload_0instrucción inserta el objeto en la variable local 0 en la pila (normalmente es el thisobjeto). istore_1almacena el entero en la parte superior de la pila en la variable local 1. Para las variables locales más allá de 3, se omite el sufijo y se deben utilizar operandos.

Ejemplo

Considere el siguiente código Java:

exterior : para ( int i = 2 ; i < 1000 ; i ++ ) { para ( int j = 2 ; j < i ; j ++ ) { si ( i % j == 0 ) continuar exterior ; } System . out . println ( i ); }                              

Un compilador de Java podría traducir el código Java anterior en código de bytes de la siguiente manera, suponiendo que lo anterior se colocó en un método:

0 : iconst_2 1 : istore_1 2 : iload_1 3 : sipush 1000 6 : if_icmpge 44 9 : iconst_2 10 : istore_2 11 : iload_2 12 : iload_1 13 : if_icmpge 31 16 : iload_1 17 : iload_2 18 : irem 19 : ifne 25 22 : goto 38 25 : iinc 2, 1 28 : goto 11 31 : getstatic #84; // Campo java/lang/System.out : Ljava/io/PrintStream; 34 : iload_1 35 : invocarvirtual #85 ; // Método java/io/PrintStream.println:(I)V 38 : iinc 1, 1 41 : ir a 2 44 : regresar                                       

Generación

El lenguaje más común que se dirige a la máquina virtual Java mediante la producción de bytecode de Java es Java. Originalmente, solo existía un compilador, el compilador javac de Sun Microsystems , que compila el código fuente de Java en bytecode de Java; pero como ahora están disponibles todas las especificaciones para el bytecode de Java, otras partes han proporcionado compiladores que producen bytecode de Java. Algunos ejemplos de otros compiladores incluyen:

Algunos proyectos proporcionan ensambladores de Java para permitir escribir código de bytes de Java a mano. El código de ensamblaje también puede generarse por máquina, por ejemplo, mediante un compilador que tenga como destino una máquina virtual de Java . Entre los ensambladores de Java más destacados se incluyen:

  • Jasmin, toma descripciones de texto para clases Java, escritas en una sintaxis simple similar a un ensamblador utilizando el conjunto de instrucciones de la máquina virtual Java y genera un archivo de clase Java [6]
  • Jamaica, un lenguaje ensamblador de macros para la máquina virtual Java . La sintaxis de Java se utiliza para la definición de clases o interfaces. Los cuerpos de los métodos se especifican mediante instrucciones de código de bytes. [7]
  • Krakatau Bytecode Tools, actualmente contiene tres herramientas: un descompilador y desensamblador para archivos de clase Java y un ensamblador para crear archivos de clase. [8]
  • Lilac, un ensamblador y desensamblador para la máquina virtual Java . [9]

Otros han desarrollado compiladores, para diferentes lenguajes de programación, para apuntar a la máquina virtual Java, como:

Ejecución

En la actualidad, existen varias máquinas virtuales Java disponibles para ejecutar bytecode de Java, tanto productos gratuitos como comerciales. Si no se desea ejecutar bytecode en una máquina virtual, un desarrollador también puede compilar código fuente de Java o bytecode directamente en código de máquina nativo con herramientas como el compilador GNU para Java (GCJ). Algunos procesadores pueden ejecutar bytecode de Java de forma nativa. Dichos procesadores se denominan procesadores Java .

Soporte para lenguajes dinámicos

La máquina virtual Java ofrece cierto soporte para lenguajes de tipado dinámico . La mayor parte del conjunto de instrucciones de la JVM existente tiene tipado estático , en el sentido de que las firmas de las llamadas a métodos se comprueban en tiempo de compilación , sin un mecanismo para posponer esta decisión hasta el tiempo de ejecución o para elegir el envío del método mediante un enfoque alternativo. [12]

JSR 292 ( Compatibilidad con lenguajes de tipado dinámico en la plataforma Java ) [13] agregó una nueva invokedynamicinstrucción en el nivel de JVM para permitir la invocación de métodos que dependen de la verificación de tipos dinámica (en lugar de la instrucción de verificación de tipos estática existente invokevirtual). La máquina Da Vinci es una implementación de máquina virtual prototipo que aloja extensiones de JVM destinadas a admitir lenguajes dinámicos. Todas las JVM que admiten JSE 7 también incluyen el invokedynamiccódigo de operación.

Véase también

Referencias

  1. ^ ab "Especificación de la máquina virtual Java". Oracle . Consultado el 14 de noviembre de 2023 .
  2. ^ de Lindholm, Tim (2015). La especificación de la máquina virtual Java . Oracle. ISBN 978-0133905908.
  3. ^ Arnold, Ken (1996). "El lenguaje de programación Java". Sun Microsystems . 1 (1): 30–40.
  4. ^ "IBM Developer". developer.ibm.com . Consultado el 20 de febrero de 2006 .
  5. ^ abcdefg Lindholm, Tim; Yellin, Frank; Bracha, Gilad; Buckley, Alex (13 de febrero de 2015). La especificación de la máquina virtual Java (Java SE 8.ª ed.).
  6. ^ "Página de inicio de Jasmin". jasmin.sourceforge.net . Consultado el 2 de junio de 2024 .
  7. ^ "Jamaica: El ensamblador de macros de la máquina virtual Java (JVM)" . Consultado el 2 de junio de 2024 .
  8. ^ "Cuentacuentos / Krakatau". 1 de junio de 2024 . Recuperado 2 de junio de 2024 - vía GitHub.
  9. ^ "Lilac - un ensamblador de Java". lilac.sourceforge.net . Consultado el 2 de junio de 2024 .
  10. ^ "Nuevas características de FPC 3.0.0 - Wiki de Free Pascal". wiki.freepascal.org . Consultado el 2 de junio de 2024 .
  11. ^ "FPC JVM - Wiki de Free Pascal". wiki.freepascal.org . Consultado el 2 de junio de 2024 .
  12. ^ Nutter, Charles (3 de enero de 2007). "InvokeDynamic: Actually Useful?" (¿InvokeDynamic: realmente útil?) . Consultado el 25 de enero de 2008 .
  13. ^ "Programa Java Community Process(SM) - JSRs: Java Specification Requests - detail JSR# 292" (El programa Java Community Process(SM) - JSR: solicitudes de especificación de Java - detalle JSR# 292). www.jcp.org . Consultado el 2 de junio de 2024 .
  • Especificación de la máquina virtual Java de Oracle
  • Lenguajes de programación para la máquina virtual de Java
  • Bytecode Visualizer: visualizador y depurador de bytecode (complemento gratuito de Eclipse)
  • AdaptJ StackTrace: depuración a nivel de bytecode con control total de la pila, las variables locales y el flujo de ejecución
  • Java Class Unpacker: complemento para Total Commander que permite abrir archivos de clase como archivos comprimidos y ver los campos y métodos como archivos. El código de bytes se puede ver como texto usando F3
Obtenido de "https://es.wikipedia.org/w/index.php?title=Código_de_bytes_de_Java&oldid=1240924187"