nazareno logo ejemplos descargar java c jvm jni native-code

java - logo - ¿Es posible usar sun.misc.Unsafe para llamar a funciones C sin JNI?



jni logo (1)

¿Es JNI tan lento?

JNI ya se ha optimizado mucho, primero debes intentarlo. Pero sí que tiene ciertos gastos generales, ver detalles .

Esta sobrecarga puede ser significativa si una función nativa es simple y se llama con frecuencia. JDK tiene una API privada llamada Critical Natives para reducir la sobrecarga de las funciones de llamada que no requieren mucha funcionalidad JNI.

Nativos Críticos

Un método nativo debe cumplir las siguientes condiciones para convertirse en un nativo crítico:

  • debe ser estático y no sincronizado ;
  • los tipos de argumento deben ser matrices primitivas o primitivas ;
  • la implementación no debe llamar a las funciones JNI, es decir, no puede asignar objetos Java o lanzar excepciones;
  • no debe funcionar durante mucho tiempo, ya que bloqueará GC mientras se ejecuta.

La declaración de un nativo crítico parece un método JNI regular, excepto que

  • comienza con JavaCritical_ lugar de Java_ ;
  • no tiene argumentos JNIEnv* y jclass ;
  • Las matrices de Java se pasan en dos argumentos: el primero es una longitud de matriz y el segundo es un puntero a los datos de matriz sin formato. Es decir, no es necesario llamar a GetArrayElements ni a sus amigos, puede usar instantáneamente un puntero de matriz directo.

Por ejemplo, un método JNI.

JNIEXPORT jint JNICALL Java_com_package_MyClass_nativeMethod(JNIEnv* env, jclass klass, jbyteArray array) { jboolean isCopy; jint length = (*env)->GetArrayLength(env, array); jbyte* buf = (*env)->GetByteArrayElements(env, array, &isCopy); jint result = process(buf, length); (*env)->ReleaseByteArrayElements(env, array, buf, JNI_ABORT); return result; }

se volverá a

JNIEXPORT jint JNICALL JavaCritical_com_package_MyClass_nativeMethod(jint length, jbyte* buf) { return process(buf, length); }

Los nativos críticos solo se admiten en HotSpot JVM a partir de JDK 7. Además, la versión "crítica" se llama solo desde el código compilado. Por lo tanto, necesita una implementación crítica y estándar para que esto funcione correctamente.

Esta característica fue diseñada para uso interno en JDK. No hay especificación pública o algo así. Probablemente la única documentación que pueda encontrar esté en los comentarios a JDK-7013347 .

Punto de referencia

Esta referencia muestra que los nativos críticos pueden ser varias veces más rápidos que los métodos JNI normales cuando la carga de trabajo nativa es muy pequeña. Cuanto más largo es el método, menor es la sobrecarga relativa.

PD: hay un trabajo en curso en JDK para implementar Manillas de Método Nativo que servirán como una alternativa más rápida a JNI. Sin embargo, es poco probable que aparezca antes de JDK 10.

  1. http://cr.openjdk.java.net/~jrose/panama/native-call-primitive.html
  2. http://mail.openjdk.java.net/pipermail/panama-dev/2015-December/000225.html

Una parte del código C / C ++ podría proporcionar un método JNI con una serie de punteros de función. Pero, ¿hay una manera de llamar a la pila a las funciones a las que apuntan los punteros de la matriz, directamente desde dentro del código Java (sin usar JNI o ​​similar)? JNI de alguna manera hace algo así, así que debe haber una manera. ¿Cómo lo hace JNI? ¿Es a través de sun.misc.Unsafe? Incluso si no lo es, ¿podríamos usar alguna solución no segura para obtener el código JVM que hace eso?

No planeo usar eso comercialmente por supuesto. Ni siquiera soy un profesional, solo disfruto mucho de la codificación y he estado estudiando CUDA últimamente, así que pensé que podría experimentar mezclando todo, pero la sobrecarga de las llamadas JNI anularía el propósito de tener un código acelerado de GPU.