3 votes

Quel est le moyen le plus rapide de marshal les données hors de JNI ?

Supposons que j'ai une structure de données C contenant de nombreux champs de données (>15) :

struct MyData
{
   int x;
   float y;
   ...
}

En Java, je peux stocker un pointeur vers une MyData en tant que long, et accéder aux membres de la structure de données C par le biais d'appels JNI :

long mydata_p = MyDataJNI.alloc();

int x = MyDataJNI.getX( mydata_p );
float y = MyDataJNI.getY( mydata_p );
...

Cependant, les appels à ces fonctions sont scandaleusement coûteux (10x-100x le coût d'un appel de fonction C équivalent). Ceci est vrai même si l'implémentation getX, getY, ... est aussi simple que :

return ((MyData*)())->x

Q1 : Pourquoi les appels JNI sont-ils si chers ? Que se passe-t-il d'autre qu'un appel à un pointeur de fonction ? (Pour référence, je regarde les appels JNI dans Android).

Q2 : Quel est le moyen le plus rapide de rendre tous les éléments de ma structure C disponibles à la couche Java ?

2voto

Russell Zahniser Points 11176

Au lieu de stocker les résultats de l'appel natif dans un pointeur géré de manière externe, vous pouvez lui demander de renvoyer le résultat dans un objet Java.

Le plus simple serait de memcpy les structs C directement dans un fichier byte[] puis, du côté de Java, d'envelopper ce tableau dans un fichier de type ByteBuffer et le lire avec getInt() , getFloat() etc.

Vous pourriez également renvoyer un tableau d'objets Java construits pour refléter vos structures, mais le code serait un fouillis incroyable, un peu comme si vous construisiez tout par réflexion avec une gestion explicite de la mémoire.

2voto

technomage Points 3774

Vous voulez déplacer toutes les données avec un seul appel JNI. Vous pouvez soit les copier dans un tableau d'octets primitif (puis en extraire les primitives Java à l'aide d'une combinaison de ByteArrayOutputStream et de DataOutputStream), soit utiliser un ByteBuffer NIO direct (ByteBuffer.allocateDirect), ce qui est plus logique si vous devez déplacer les données dans les deux sens. Le ByteBuffer direct est spécifiquement conçu et optimisé pour le partage de la mémoire entre la VM et le code natif.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X