JNI : références locales réutilisables ou non ?
Dans ce tuto sur JNI (et dans bien d'autres), il est écrit clairement qu'on ne doit pas garder une référence locale pour une réutilisation future :
Citation:
By default, JNI creates local references to ensure that they are liable for garbage collection. Because of this, you may unintentionally write illegal code by trying to store away a local reference so that you can reuse it later, as shown in the code sample below:
Code:
1 2 3 4 5 6 7 8 9 10 11 12
| /* This code is invalid! */
static jmethodID mid;
JNIEXPORT jstring JNICALL
Java_Sample1_accessMethod(JNIEnv *env, jobject obj)
{
...
cls = (*env)->GetObjectClass(env, obj);
if (cls != 0)
mid = (*env)->GetStaticMethodID(env, cls, "addInt", "(I)I");
...
} |
Maintenant, je regarde les sources de java.net.PlainDatagramSocketImpl en Java, et je veux connaître l'implémentation native de :
Code:
protected synchronized native void receive0(DatagramPacket p) throws IOException;
Je regarde ce qui pourrait correspondre :
Code:
1 2 3 4 5
| $ grep -rl receive0 | grep '\.c$'
jdk/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c
jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c
jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c
jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c |
Je trouve donc jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c.
Dedans, il y a plein de jfieldID en tant que variables externes static. Par exemple :
Code:
1 2 3 4 5 6 7 8 9
| static jfieldID IO_fd_fdID;
static jfieldID pdsi_fdID;
static jfieldID pdsi_timeoutID;
static jfieldID pdsi_trafficClassID;
static jfieldID pdsi_localPortID;
static jfieldID pdsi_connected;
static jfieldID pdsi_connectedAddress;
static jfieldID pdsi_connectedPort; |
Le début de l'implémentation du constructeur :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| /*
* Class: java_net_PlainDatagramSocketImpl
* Method: init
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_java_net_PlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) {
#ifdef __linux__
struct utsname sysinfo;
#endif
char *s;
pdsi_fdID = (*env)->GetFieldID(env, cls, "fd",
"Ljava/io/FileDescriptor;");
CHECK_NULL(pdsi_fdID);
pdsi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I"); |
Et voici le début de l'implémentation de la méthode receive0 :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| /*
* Class: java_net_PlainDatagramSocketImpl
* Method: receive
* Signature: (Ljava/net/DatagramPacket;)V
*/
JNIEXPORT void JNICALL
Java_java_net_PlainDatagramSocketImpl_receive0(JNIEnv *env, jobject this,
jobject packet) {
char BUF[MAX_BUFFER_LEN];
char *fullPacket = NULL;
int mallocedPacket = JNI_FALSE;
jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
jint timeout = (*env)->GetIntField(env, this, pdsi_timeoutID); |
Précisément ce qu'il ne faut pas faire, non ?
Qui a raison ? Le tuto ou l'implémentation des bibliothèques standard ?
Merci de votre aide.