I’ve spent whole day on this problem and still have no idea how to solve it.
Here is the simplified code
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 is executed in some loop, which stops when C++ catches isTerminated().
In output i see:
….
….
in log:
java 0
java 1
java 1
java 1
in console:
JNI 0
JNI 0
JNI 0
JNI 1
So, JNI is somehow behind the real state of variable.
It produces an important bug in application (((
Maybe it’s some problem with java itself? (v.1.5, i forced to used it)
Any help is greatly appreciated.
I would suggest doing all the synchronization in one language or the other. It’s looking like “volatile” isn’t being respected across the boundary for some reason. Something like: