2009-02-17 8 views
33

Si nos fijamos en la clase de objetos de Java entonces podemos encontrar algunos de los métodos como:¿Qué es una implementación nativa en Java?

public native int hashCode() 
protected native Object clone() 

¿Cuáles son estos nativos y cómo funcionan estos métodos?

Respuesta

34

Estos métodos son intrínseco o escrito fuera de Java en código "nativo", es decir, específico para la máquina dada.

los que mencionas son intrínseca y parte del JDK pero también se puede escribir métodos nativos por sí mismo utilizando la Java Native Interface (JNI). Esto normalmente usaría C para escribir los métodos, pero muchos otros lenguajes, como python, le permiten escribir métodos de esta manera con bastante facilidad. El código está escrito de esta manera, ya sea para el rendimiento, o porque necesita acceder a la infraestructura específica de la plataforma que no se puede hacer en Java simple.

En el caso de hashcode(), esto es implementado por la JVM. Esto se debe a que a menudo el código hash se relacionará con algo que solo la JVM conoce. En las primeras JVM esto estaba relacionado con la ubicación del objeto en la memoria: en otras JVM, el objeto puede moverse en la memoria, por lo que se puede usar un esquema más complicado (pero aún muy rápido).

+6

si hashcode() está implementado por JVM solo ¿por qué requiere ser * native *? ¿A qué se refiere con * intrínseco * aquí? – Geek

11

Los métodos nativos se implementan principalmente en C y se compilan en código nativo que se ejecuta directamente en la máquina. Esto está en contraste con los métodos normales, que se implementan en Java y se compilan en el código de bytes de Java, que es ejecutado por la Máquina Virtual Java (JVM).

Para interactuar con estos métodos desde Java necesita usar el Java Native Interface (JNI).

El código nativo es principalmente necesario para acceder a cosas de bajo nivel. En el caso de hashCode esta es la dirección del objeto en la memoria. Mi conjetura para clon es que copia la memoria cruda de un objeto de dar al clonado. Otros usos del código nativo son para acceder a las características o el hardware del sistema operativo.

El inconveniente de utilizar código nativo es que pierde la seguridad de la JVM, es decir, su programa puede bloquearse o tener agujeros de seguridad debido a errores en el código nativo.

17

La mayoría de los métodos nativos se implementan utilizando JNI como se menciona en otras respuestas.

Sin embargo, los métodos críticos de rendimiento como Object.hashCode se implementan típicamente como intrínsecos. Cuando el código de bytes se compila en código máquina, el compilador de Java reconoce la llamada al método e ingresa el código apropiado directamente. Obviamente, esto va a ser mucho más rápido que pasar por JNI por un método trivial.

Muchas personas afirman que Object.hashCode devolverá la dirección de la representación del objeto en la memoria. En las implementaciones modernas, los objetos se mueven dentro de la memoria. En cambio, se usa un área del encabezado del objeto para almacenar el valor, que puede derivarse de forma perezosa de la dirección de la memoria en el momento en que se solicita el valor por primera vez.

+2

Para más detalles [visita] (http://stackoverflow.com/a/13860488/390695) –

10

¿Qué son estos nativos y cómo funcionan estos métodos?

ejemplo Mínimo para hacer las cosas más claras:

Main.java:

public class Main { 
    public native int square(int i); 
    public static void main(String[] args) { 
     System.loadLibrary("Main"); 
     System.out.println(new Main().square(2)); 
    } 
} 

Main.c:

#include <jni.h> 
#include "Main.h" 

JNIEXPORT jint JNICALL Java_Main_square(
    JNIEnv *env, jobject obj, jint i) { 
    return i * i; 
} 

Compilar y ejecutar:

sudo apt-get install build-essential openjdk-7-jdk 
export JAVA_HOME='/usr/lib/jvm/java-7-openjdk-amd64' 
javac Main.java 
javah -jni Main 
gcc -shared -fpic -o libMain.so -I${JAVA_HOME}/include \ 
    -I${JAVA_HOME}/include/linux Main.c 
java -Djava.library.path=. Main 

salida:

4 

probado en Ubuntu 14.04. También trabajé con Oracle JDK 1.8.0_45.

Example on GitHub para que juegues con.

Interpretación:

Se le permite:

  • llamada de una biblioteca cargada dinámicamente compilado (aquí escrito en C) con el código de montaje arbitraria desde Java
  • y obtener resultados de nuevo en Java

Esto podría usarse para:

  • escribir código más rápido en una sección crítica con las instrucciones de la CPU mejor montaje (no portátiles CPU)
  • realizar llamadas de sistema directo (no OS portátil)

con la compensación de la portabilidad inferior.

También es posible que usted pueda llamar a Java desde C, pero primero debe crear una JVM en C: How to call Java functions from C++?

Ejemplo en el OpenJDK 8

vamos a encontrar encontrar dónde Object#clone se define en jdk8u60-b27.

En primer lugar nos encontramos con:

find . -name Object.java 

que nos lleva a jdk/src/share/classes/java/lang/Object.java#l212:

protected native Object clone() throws CloneNotSupportedException; 

Ahora viene la parte difícil, encontrar dónde clon es en medio de toda la vía indirecta. La consulta que me ayudó fue:

find . -iname object.c 

que encontraría archivos C o C++ que podrían implementar los métodos nativos de Object.Nos lleva a jdk/share/native/java/lang/Object.c#l47:

static JNINativeMethod methods[] = { 
    ... 
    {"clone",  "()Ljava/lang/Object;", (void *)&JVM_Clone}, 
}; 

JNIEXPORT void JNICALL 
Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls) 
{ 
    (*env)->RegisterNatives(env, cls, 
          methods, sizeof(methods)/sizeof(methods[0])); 
} 

que nos lleva al símbolo JVM_Clone:

grep -R JVM_Clone 

que nos lleva a hotspot/src/share/vm/prims/jvm.cpp#l580:

JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle)) 
    JVMWrapper("JVM_Clone"); 

Después de expandir un grupo de macros, llegamos a la conclusión de que este es el punto de definición.

Cuestiones relacionadas