¿Hay funciones en línea en java?


112

¿Existe un concepto de funciones en línea en Java, o se reemplazó por algo más? Si lo hay, ¿cómo se usa? Escuché eso public, staticy los finalmétodos son las funciones en línea. ¿Podemos crear nuestra propia función en línea?


4
Solo para aclarar, te refieres a en.wikipedia.org/wiki/Inline_function , no a en.wikipedia.org/wiki/Anonymous_function , ¿verdad?
JW.

3
Como comentario menor, la optimización prematura es la raíz de todos los males. Sin una comprensión completa de la naturaleza de público, estático y final, no es posible comprender realmente el impacto que puede tener la alineación interna, y eso depende de la JVM que esté utilizando. Asegúrese de responder primero por qué necesita incorporar algo: es casi seguro que hay optimizaciones de ROI más altas que puede hacer en otros lugares.
Nathaniel Ford

Respuestas:


123

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

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

Para más recursos:

  1. Artículo: El motor de rendimiento de Java HotSpot: ejemplo de inserción de métodos

  2. Wiki: incluido en OpenJDK , no está completamente poblado pero contiene enlaces a discusiones útiles.


15

No, no hay una función en línea en java. Sí, puede usar un método estático público en cualquier parte del código cuando se coloca en una clase pública. El compilador de Java puede hacer una expansión en línea 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. Además, 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 mediante una declaración en java, sino que se realizan mediante el compilador y JIT. En muchos otros lenguajes, estas declaraciones a menudo son solo sugerencias del compilador (puede declarar más parámetros de registro que los que tiene el procesador, el resto se ignora).

Declarar los métodos Java estáticos, finales o privados también son sugerencias para el compilador. Debería usarlo, pero sin 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 clases. 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 dentro del sistema en ejecución, por lo que un servidor puede volverse más rápido durante el tiempo de ejecución.


3
finalhacer ningún impacto en procesos en línea JIT
Steve Kuo

1
+1, pero ¿cómo podemos probar si la versión compilada de un método está insertada?
Pacerier

@Pacerier Pero, ¿por qué deberíamos probar si algo está en línea?
Arne Burmeister

14

Java no proporciona una forma de sugerir manualmente que un método debe estar insertado. Como dice @notnoop en los comentarios, la JVM suele realizar la inserción en el momento de la ejecución.


3
La mayoría de los compiladores de Java nunca llaman a métodos en línea. Sobre todo, la JVM hace eso.
notnoop

Gracias por aclarar eso. No estaba seguro de en qué fase sucedió exactamente. Editaré mi publicación para reflejar eso.
Thomas Owens

@ThomasOwens lo hace, pero no es públicojdk.internal.vm.annotation.ForceInline
Eugene

4

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


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

4
En HotSpot, agregar finalni siquiera hace ninguna diferencia en cuanto a si el método está integrado o no.
Tom Hawtin - tackline

4
@Thomas - por eso dije "A veces métodos finales ..."
GreenieMeanie

@ TomHawtin-tackline ¿tiene una fuente autorizada para eso? Hasta donde yo sé, los métodos finales se pueden insertar sin emplear un tipo de protección, lo que significa que el modificador hace que el método sea más eficiente que sin el modificador. Sé que Jikes RVM tiene esto en cuenta al decidir si se integra. ¿Estás seguro de que HotSpot no hace algo similar?
Jannik Jochem

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);
    }
}

Luego, 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, lo que dificulta rastrear todos los lugares en el código que verifica la fecha de vencimiento. 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 bueno forzar a un compilador a incorporar el método final estático a todas las clases que lo hacen referencia. En ese caso, ni siquiera necesita incluir la clase Control, ya que no sería necesaria en tiempo de ejecución.

Según mi investigación, esto no se puede hacer. Quizás algunas herramientas de Obfuscator puedan hacer esto, o podría modificar su proceso de compilación para editar las fuentes antes de compilar.

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 la ruta de clases.


2

Bueno, hay métodos que podrían llamarse métodos "en línea" en Java, pero dependiendo del archivo jvm. Después de la compilación, si el código de máquina del método tiene menos de 35 bytes, se transferirá a un método en línea de inmediato; si el código de máquina del método tiene menos de 325 bytes, se puede transferir a un método en línea, según el jvm.


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

0

entonces, parece que no los hay, pero puede usar esta solución usando guava o una implementación de clase de función equivalente, porque esa clase es extremadamente simple, por ejemplo:

    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í, este es un código muerto solo 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 ello, también conocido como en línea.


Parece una idea razonable. ¿Tiene 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, lo que puede verse como en línea.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.