2012-05-12 10 views
7

En bytecode java, ¿por qué el receptor se inserta primero en la pila seguido de todos los parámetros? Me parece recordar que es algo relacionado con la eficiencia.Orden de bytes de Java Byte y parámetros en la pila

Esto es válido tanto para las llamadas al método como para los campos de configuración.

método de llamada de

class X { 

    int p(int a) { 
     //Do something 
    } 
    int main() { 
     int ret = p(1); 
    } 

} 

método Main compila a:

aload_0 // Load this onto the stack 
iconst_1 // Load constant 1 onto the stack 
invokevirtual <int p(int)> from class X 

Colocando un campo:

class X { 
    int x; 
    int main() { 
     x = 1; 
    } 

} 

método Main compila a:

aload_0 // Load this onto the stack 
iconst_1 // Load constant 1 onto the stack 
putfield <int x> from class X 
+0

Creo que lo he entendido, pero no puedo responder ya que no tengo suficientes puntos. –

+0

Esta es una de esas preguntas de "curiosidad inactiva". Interesante, pero la respuesta es de ningún uso práctico ... a menos que esté contemplando el diseño de un nuevo conjunto de instrucciones bytecode. –

+1

tu punto es? Aprender cómo funciona una computadora es una pregunta de "curiosidad inactiva" para la mayoría. –

Respuesta

1

Siendo empujado primero tiene la ventaja de que el método

  • El destino puede utilizar el más denso "aload0" código de bytes (más pequeño que si fuera mucho más tarde en la lista de parámetros y tuvo que usar una versión paramétrica de el código de bytes aload. Debido a que "esto" a menudo se referencia en métodos para el acceso de campo y método, conduce a una mejora de densidad de código real.
  • Uno a menudo envía envíos de métodos en cascada como "foo.bar(). baz()" Cuando bar() regresa, , el futuro "this" para .baz() ya está mágicamente en el lugar correcto en el apila si arreglas las cosas como se hizo en Java.
+0

Estas respuestas son verosímiles, pero en realidad los códigos de bytes se compilan en código nativo, y ninguna de estas ventajas funciona una vez que eso ocurre. –

+0

Eso no es correcto para el segundo punto en la mayoría de las arquitecturas RISC como POWER, donde tanto los parámetros como los valores devueltos están realmente en registros. Hacer que se alineen correctamente (return -> arg 0) funciona muy bien y mejora el rendimiento. Además, en el primer punto, aunque 1 byte no parece mucho, la JVM a menudo tiene que mantener los códigos de bytes en la memoria (piense en la reescritura de clases, etc. de JVMTI) y suma todos los bytes guardados de 1 en miles de clases se suma a la memoria no trivial. –

+0

Está asumiendo que el diseño de pila virtual en el modelo de bytecode se asemeja al diseño de pila física utilizado por el código compilado JIT. ¿Puedes justificar esa suposición? El uso de la memoria Re, un ahorro de decenas o cientos de miles de bytes de bytecode >> es << trivial ... en máquinas con gigabytes de memoria física. Además, una vez que los códigos de bytes están compilados JIT, pueden ser recolectados. (No estoy seguro si lo son ...) Y la optimización para el caso JVMTI parece algo sin sentido. –

1

¿Estás preguntando por qué se empuja en absoluto? En ambos casos, estás accediendo a algo que pertenece a una instancia de la clase, por lo que this tiene que ser parte de ese proceso.

¿Estás preguntando por qué se empuja primero? Sólo la convención de Java. Supongo que es conveniente tener siempre this primero, independientemente de las muchas cosas que podrían seguir.

+0

Preguntando esto último. Los ejemplos muestran claramente que sé por qué esto está allí. Esa es la razón por la que pensé, pero no me dejaba publicar. No parece estar basado en la eficiencia ya que estoy seguro de que me lo dijeron. Hipotéticamente, incluso si esto fue lo último, todavía debería ser capaz de resolver la posición de él estáticamente en la compilación. No puedo pensar en nada que signifique que no puedes, aunque solo sé constructos de JVM muy básicos. –

Cuestiones relacionadas