2010-01-19 24 views
88

¿Existe un concepto de funciones en línea en java, o se reemplazó algo más? Si hay, ¿cómo se usa? Escuché que los métodos public, static y final son funciones en línea. ¿Podemos crear nuestra propia función en línea?¿Hay funciones en línea en Java?

+3

Solo para aclarar, te refieres a http://en.wikipedia.org/wiki/Inline_function, no a http://en.wikipedia.org/wiki/Anonymous_function, ¿verdad? –

+3

Como comentario menor, la optimización prematura es la raíz de todo mal. Si no se comprende por completo la naturaleza del público, estático y final, no se puede entender realmente el impacto que podría tener la información en línea, y eso depende de la JVM que se esté utilizando. Asegúrese de responder primero por qué necesita alinear algo: es casi seguro que hay mayores optimizaciones de ROI que puede hacer en otros lugares. –

+0

También vea http://stackoverflow.com/q/7772864/632951 – Pacerier

Respuesta

4

Lo que dice arriba es correcto. A veces los métodos finales se crean como en línea, pero no hay otra manera de crear explícitamente una función en línea en java.

+4

No se garantiza que los métodos finales estén en línea. –

+3

En HotSpot, agregar 'final' no hace ninguna diferencia en cuanto a si el método está en línea o no. –

+4

@Thomas - por lo que dije "A veces los métodos finales ..." – GreenieMeanie

103

En Java, las optimizaciones generalmente se realizan a nivel de JVM. En tiempo de ejecución, la JVM realiza algunos análisis "complicados" para determinar qué métodos aplicar en línea. Puede ser agresivo en la creación de líneas, y la JVM de Hotspot en realidad puede alinear métodos no finales.

Los compiladores java casi nunca incluyen ninguna llamada a método (la JVM hace todo eso en tiempo de ejecución). Hacen constantes de tiempo de compilación en línea (por ejemplo, valores primitivos estáticos finales). Pero no métodos

Para obtener más recursos:

  1. Article: The Java HotSpot Performance Engine: Method Inlining Example

  2. Wiki: Inlining in OpenJDK, no totalmente poblada pero contiene enlaces a discusiones útiles.

12

Java no proporciona una forma de sugerir manualmente que un método debe estar en línea. Como dice @notnoop en los comentarios, la JVM generalmente hace la alineación en el momento de la ejecución.

+3

La mayoría de los compiladores de Java nunca hacen llamadas en línea. Sobre todo, la JVM hace eso. – notnoop

+0

Gracias por aclarar eso. No estaba seguro en qué fase ocurrió exactamente. Editaré mi publicación para reflejar eso. –

9

No, no hay inline function en java. Sí, puede utilizar un método público estático en cualquier lugar del código cuando se lo coloca en una clase pública. El compilador de Java puede hacer inline expansion en un método estático o final, pero eso no está garantizado.

Normalmente, el compilador realiza estas optimizaciones de código en combinación con JVM/JIT/HotSpot para los segmentos de código que se utilizan con mucha frecuencia. También otros conceptos de optimización como la declaración de registro de parámetros no se conocen en Java.

Las optimizaciones no se pueden forzar por declaración en java, pero se hacen por compilador y JIT. En muchos otros idiomas, estas declaraciones a menudo son solo sugerencias del compilador (puede declarar más parámetros de registro que el procesador, el resto se ignora).

Declarar los métodos java estáticos, finales o privados también son sugerencias para el compilador. Deberías usarlo, pero no hay garantías. El rendimiento de Java es dinámico, no estático. La primera llamada a un sistema siempre es lenta debido a la carga de clase. Las siguientes llamadas son más rápidas, pero dependiendo de la memoria y el tiempo de ejecución, las llamadas más comunes se optimizan con el sistema en ejecución, ¡de modo que un servidor puede volverse más rápido durante el tiempo de ejecución!

+1

'final' no afecta a JIT enlining –

+1

+1, pero ¿cómo podemos ** probar ** si la versión compilada de un método está en línea? – Pacerier

2

ejemplo de la vida real:

public class Control { 
    public static final long EXPIRED_ON = 1386082988202l; 
    public static final boolean isExpired() { 
     return (System.currentTimeMillis() > EXPIRED_ON); 
    } 
} 

Entonces en otras clases, puedo salir si el código ha expirado. Si hago referencia a la variable EXPIRED_ON de otra clase, la constante está en línea con el código de bytes, por lo que es muy difícil rastrear todos los lugares en el código que verifica la fecha de caducidad. Sin embargo, si las otras clases invocan el método isExpired(), se llama al método real, lo que significa que un pirata informático podría reemplazar el método isExpired por otro que siempre devuelve falso.

Estoy de acuerdo en que sería muy útil obligar a un compilador a incorporar el método estático final a todas las clases que hacen referencia a él.En ese caso, ni siquiera necesita incluir la clase Control, ya que no sería necesaria en el tiempo de ejecución.

De mi investigación, esto no se puede hacer. Quizás algunas herramientas de Obfuscator puedan hacer esto, o bien, podrías modificar tu proceso de compilación para editar las fuentes antes de compilarlas.

En cuanto a probar si el método de la clase de control se coloca en línea con otra clase durante la compilación, intente ejecutar la otra clase sin la clase Control en el classpath.

0

Bueno, hay métodos que podrían llamarse métodos "en línea" en Java, pero dependiendo de jvm. Después de compilar, si el código máquina del método es inferior a 35 bytes, se transferirá a un método en línea de inmediato, si el código máquina del método es inferior a 325 bytes, podría transferirse a un método en línea, según el jvm.

+0

Estos son * valores * predeterminados para la máquina virtual de Oracle, consulte http://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html – rmuller

0

así, parece que enviaban, pero se puede utilizar esta solución usando la guayaba o un equivalente implementación de la clase de funciones, debido a que la clase es extremadamente simple, ej .:

assert false : new com.google.common.base.Function<Void,String>(){ 
     @Override public String apply(Void input) { 
      //your complex code go here 
      return "weird message"; 
     }}.apply(null); 

sí, esto es simplemente el código muerto para ejemplificar cómo crear un bloque de código complejo (dentro de {}) para hacer algo tan específico que no debería molestarnos en crear ningún método para él, ¡AKA inline!

+0

Parece una idea razonable. ¿Tienes una versión de esto que no usa las bibliotecas comunes de Google? – ragerdl

0

Java9 tiene un compilador "Ahead of time" que realiza varias optimizaciones en tiempo de compilación, en lugar de en tiempo de ejecución, que se puede ver como en línea.