Pregunta

métodos finales son Java automáticamente entre líneas?

Muchos libros dice que sí muchos libros dice que no !!!

¿Fue útil?

Solución

Una pregunta interesante, me impulsó a investigar más a fondo. 2 observaciones interesantes que encontraron -

  

A diferencia de la implicación de muchos   consejos, métodos declarados como final no puede   ser inline con seguridad por el compilador,   debido a que el método podría tener una   declaración no final en tiempo de ejecución.

     

Para ver por qué, supongamos que las miradas del compilador   en la clase A y subclase B, y   sub-subclase C y ve un método final   en A que inlines en C. Pero entonces   en tiempo de ejecución las versiones cargados para A   y B son diferentes y el método es   no es definitiva en A, y se reemplaza en B.   Entonces C utiliza el incorrectamente inline   versión. T

Y, un poco más con autoridad, a partir de una sol libro blanco, la escritura que los métodos se pueden dejar virtual,

  

Debido a que el Java HotSpot VM puede inline automáticamente la inmensa mayoría de las llamadas a métodos virtuales, esta penalización en el rendimiento se reduce drásticamente, y en muchos casos, eliminó por completo.

Aquí hay una referencia más directo sobre el mecanismo.

Otros consejos

Inlining de métodos se lleva a cabo por el compilador JIT, no javac.

compiladores JIT modernos (incluyendo Hotspot) a menudo pueden inline incluso los métodos no finales, "deshacer" la optimización adecuadamente si es necesario. Básicamente son aterradoramente inteligente.

En resumen: que depende enteramente de la máquina virtual. En mi opinión, usted debe hacer que sus métodos definitiva o no, sobre la base de lo que produce el código más limpio en lugar de rendimiento. Personalmente, soy un fan de "diseño para la herencia o prohibida," pero eso es una discusión diferente:)

Si usted quiere decir "¿Reciben entre líneas durante la compilación", pues no, no lo harán.

Sin embargo, los campos static final a veces puede ser inline por el compilador, por ejemplo, primitivas y cuerdas.

final es más acerca de la adición de la semántica a un diseño que decirle a un compilador o máquina virtual para inline algo. Moderno máquinas virtuales en línea mucho más que solamente métodos finales, así que esto no es una buena razón para usar final o tratar de predecir demasiado acerca de optimizaciones de tiempo de ejecución.

Creo que eso depende de lo que la implementación de la JVM está ejecutando sucesivamente. Desde luego, haciendo un último método permite al compilador la opción de hacer un pellizco dicha aplicación. Pero si lo hace o no puede depender también de otros factores - por ejemplo, ¿y si es un método enorme, etc .....

La decisión del hotspot de si se debe inline es increíblemente complicado, depende de un gran número de consideraciones, pero no creo que si está marcado el método "final" es uno de ellos. La razón es que ya es consciente de que múltiples implementaciones de este método se han cargado en la máquina virtual, por lo que es irrelevante saber también si tales implementaciones están permitidos.

En cualquier caso, sólo va a ser métodos muy pequeñas y sencillas que consiguen inline, y ni siquiera todos ellos.

Como Jon dijo que la expansión en línea se lleva a cabo (cuando sea necesario) por el compilador JIT no a nivel de generación de código de bytes. Tenga en cuenta también que a veces inlining puede resultar en una disminución del rendimiento, ya que podría crear una situación en la que el mismo código se presente varias veces en la caché L1 de la CPU, la eliminación de espacio para otro tipo de código. Fallos de caché L1 pueden afectar al rendimiento más que un salto a una función de caché.

Constantes (aka var static final) se inline su lugar.

Ver esto para comprobar

public class InlineTest {
    final static int add(int x, int y) {
        return x + y;
    } 
}


public class Main {

        static final int DIVISOR = 7;

        static void main(String[] args){
            final int a = new Integer(args[0]);
            final int b = new Integer(args[1]);

            if (InlineTest.add(a, b) % DIVISOR == 0)
                System.exit(InlineTest.add(a, b));

            System.out.print("The sum is " + InlineTest.add(a, b));

        }
}

Esto se traduce en:

 0 new #2 <java/lang/Integer>
 3 dup
 4 aload_0
 5 iconst_0
 6 aaload
 7 invokespecial #3 <java/lang/Integer/<init>(Ljava/lang/String;)V>
10 invokevirtual #4 <java/lang/Integer/intValue()I>
13 istore_1
14 new #2 <java/lang/Integer>
17 dup
18 aload_0
19 iconst_1
20 aaload
21 invokespecial #3 <java/lang/Integer/<init>(Ljava/lang/String;)V>
24 invokevirtual #4 <java/lang/Integer/intValue()I>
27 istore_2
28 iload_1
29 iload_2
30 invokestatic #5 <com/gamasoft/InlineTest/add(II)I>
33 bipush 7
35 irem
36 ifne 47 (+11)
39 iload_1
40 iload_2
41 invokestatic #5 <com/gamasoft/InlineTest/add(II)I>
44 invokestatic #7 <java/lang/System/exit(I)V>
47 getstatic #8 <java/lang/System/out Ljava/io/PrintStream;>
50 new #9 <java/lang/StringBuilder>
53 dup
54 invokespecial #10 <java/lang/StringBuilder/<init>()V>
57 ldc #11 <The sum is >
59 invokevirtual #12 <java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;>
62 iload_1
63 iload_2
64 invokestatic #5 <com/gamasoft/InlineTest/add(II)I>
67 invokevirtual #13 <java/lang/StringBuilder/append(I)Ljava/lang/StringBuilder;>
70 invokevirtual #14 <java/lang/StringBuilder/toString()Ljava/lang/String;>
73 invokevirtual #15 <java/io/PrintStream/print(Ljava/lang/String;)V>
76 return

Se puede ver que la función estática InlineTest.add se ha llamado varias veces con invokestatic

scroll top