2010-07-15 4 views
2

J'ai passé toute la journée sur ce problème et je n'ai toujours aucune idée de la façon de le résoudre.La méthode JNI renvoie les anciennes données

Voici le code simplifié

JAVA

 

class javaclass{ 
private volatile boolean isTerminated; 
    public void javamethod() 
    { 
    log.logInfo("java :"+isTerminated()); 
    } 

    public int isTerminated() 
    { 
    return (isTerminated) ? 1 : 0; 
    } 

    public doJob() 
    { 
    executeNative(); 
    } 

    private native int executeNative() throws Exception; 
} 
 

C++

 

bool cmethod() 
{ 
cerr << "JNI " << wrapper::isTerminated() << "\n"; 
if(wrapper::isTerminated) 
    return false; 
jni->CallVoidMethod(self, apiJavamethod, xPoint); 
return true; 
//apiJavamethod is jMethodId of javamethod 
} 

int wrapper::isTerminated() 
{ 
    return jni->CallIntMethod(self, apiIsTerminated); 
} 

JNIEXPORT jint JNICALL NAMESPACE_javaclass_executeNative(JNIEnv* env, jobject self) { 
    for(int i=0;i < _ITERATIONS;++i) 
    { 
    if(!cmethod()) 
     break; 
    } 

} 
 

C++ cMethod est exécuté dans une boucle, qui arrête lorsque les captures C++ isTerminated(). En sortie je vois:

.... ....

dans le journal: java 0 java 1 java 1 java 1

dans la console: JNI 0 JNI 0 JNI 0 JNI 1

Donc, JNI est en quelque sorte derrière l'état réel de la variable. Il produit un bug important dans l'application (((

Peut-être qu'il est un problème avec Java lui-même? (V.1.5, je forcé de utilisé)

Toute aide est grandement appréciée.

+0

Vous imprimez stdout de Java, et stderr de C++. Vous ne pouvez pas être certain de la w Ils sont entrelacés par votre terminal. Pour être sûr de ce qui se passe, imprimez sur le même flux dans les deux langues et videz le flux après l'impression. – Thomas

+0

oh, je vois, merci. c'est un exemple simplifié, en code réel en java j'utilise du logger GUI (le programme lui-même est un plugin au CAD) – ALOR

+0

Je suggère que vous donniez plus de code, il n'y a même pas de méthode native dans votre code jusqu'à présent. –

Répondre

1

Je voudrais conseille de faire toute la synchronisation dans une langue ou l'autre, il est à la recherche comme « volatile » n'est pas respectée à travers la frontière pour une raison quelconque Quelque chose comme:..

public doJob() 
{ 
    while(!isTerminated) 
    executeNative(); 
} 
+0

Moi aussi. Code un peu plus compliqué, mais l'idée est la même. Cela fonctionne, bien sûr ...La chose est - je ne comprends toujours pas comment ce problème est apparu et où je peux trouver des documents standard où le comportement JNI est décrit en détail ... – ALOR

+0

Ceci est probablement un bug avec l'implémentation plutôt que le comportement spécifié. Cela peut fonctionner correctement sur un autre système d'exploitation, par exemple. Vous devriez probablement regarder le code source pour voir comment cela fonctionne. –

Questions connexes