JNI - really big troubles

C

Clemens Arth

I got some quite annoying problems trying to call some Java functions
from my C++ program via JNI. Yesterday I spent about 8 hours just to
figure out what's wrong - without success. Because it's quite a
difficult problem, my description will be a little longer than common
usual.

INTRODUCTION

For testing purposes only I compiled this little Java class:

/**** XMLMessenger.java ****/

import java.io.*;

class XMLMessenger {

private static XMLMessenger xmlmsger = null;

private XMLMessenger(){ }

public static void initNatPub(String routerId, String agentId)
{
System.out.println("initNat...");
if (xmlmsger == null) { xmlmsger = new XMLMessenger(); }
}

public static boolean pubPicData(String stationId, String timeStamp)
{
System.out.println("pubPicData...");
// should do something a little later....
return true;
}

public static boolean pubSensData(String stationId, String timeStamp)
{
System.out.println("pubSensData...");
// should do something a little later....
return true;
}

}

/*****************************/

It has got a private constructor to realize the singleton pattern and
no "main" method. The code is compilable without errors and the
methods can be called from any other java program.

Using JNI I did the following:

* Start a JVM
* Attach the running thread to the JVM
* Run the following C++-Code:

/******* SNIP FROM C++ ********/

jclass ucls = env->FindClass("XMLMessenger");

jmethodID nativeId =
env->GetStaticMethodID(cls,"initNatPub","(Ljava/lang/String;Ljava/lang/String)V");

jobjectArray args = env->NewObjectArray(2,env->FindClass("java/lang/String"),env->NewStringUTF(""));
env->SetObjectArrayElement(args,0,env->NewStringUTF(ROUTERID));
env->SetObjectArrayElement(args,1,env->NewStringUTF(AGENTID));

// call only once
env->CallStaticVoidMethod(ucls,nativeId,args);

jmethodID pubSensId =
env->GetStaticMethodID(ucls,"pubSensData","(Ljava/lang/String;Ljava/lang/String)Z");
jmethodID pubPicId =
env->GetStaticMethodID(ucls,"pubPicData","(Ljava/lang/String;Ljava/lang/String)Z");

for(int x = 0; x < 10; x++)
{
jvalue arguments[2];
arguments[0].l = env->NewStringUTF("1");
arguments[1].l = env->NewStringUTF("2");
env->CallStaticBooleanMethodA(ucls,pubSensId,sensorargs);


jvalue picargs[2];
picargs[0].l = env->NewStringUTF("1");
picargs[0].l = env->NewStringUTF("2");
env->CallStaticBooleanMethodA(ucls,pubPicId,picargs);
}

/*****************************/

Everything is ok. Code is compilable without errors and the program
works without problems when the initNative-method is called before the
other both methods are used.




AND HERE IS THE PROBLEM DESCRIPTION:

I got a whole package of classes. The only class which is of any
interest for me is
xxx.xxxx.xxxx.xxx.NetPub. Here's some code:

/********* NatPub.java *********/

import 'about 10 packages';

public class NatPub extends AbsPub {

private static NatPub natPub = null;

private NatPub(int value) throws XYException
{
super(value);
}

public static void initNatPub(String routerId, String agentId)
{
if(natPub == null) { System.out.println("natPub = null"); } // keep
an eye on this!!!
if(natPub != null) { System.out.println("natPub = not null"); } //
keep an eye on this!!!

if(natPub == null)
{
try {
natPub = new NatPub(123456789);
} catch ( XYException e )
{
e.printStackTrace();
}
}

public static boolean pubPicData(String stationId, String timeStamp)
{
if(natPub != null)
{
// do something
}
}

public static boolean pubSensData(String stationId, String timeStamp)
{
if(natPub != null)
{
// do something
}
}

/*****************************/

You might notice the similarities between the two Java-classes
mentioned above. If I call the Java-Functions from ANY other
Java-Program, everything works fine.

First attempt:
If I try to use the C++ code from above the class is found without any
problems, but the JVM crashes because the two MethodIDs cannot be
retrieved by the GetStaticMethodId calls AFTER the
"env->CallStaticVoidMethod(ucls,nativeId,args);" call; The first Id is
fetched without problems. Why does the other calls to
GetStaticMethodId fail???

Second attempt:
if I wrap around the C++ code to fetch the IDs before this
initNative.. call, everything seems to be fine. But then, if I put
some "System.out.println"s into the Java code a very strange
thing happens in the initNatPub method: an evaluation of "natPub ==
null" is 'false' and an evaluation of "natPub != null" is also
'false'. WHAT THE F....K??????? The private instance of NatPub is
never created because of this evaluation. But much more confusing is
why this private object can and cannot be null at the same time
!?!?!?!?

Third attempt:
I hacked the initNative.. method to create a new NatPub anyway (no
'if(natPub == null)' condition). This throws no exception and seems to
work, but the instance of netPub is null when I call the pubPicData or
pubSensData method the next time....



I'm really in big desperation. I've never seen such strange behaviour
in any C++ or Java program before... I'm really sorry that my error
description is that long, but I don't know what to do now. Maybe
anyone has got a simple answer to one of the problems mentioned above.
Anyway I don't want to spend another 8 or more hours to search for an
error I don't really know where it is...

Best regards!
Clemens


GCC: gcc version 3.3.4 20040623 (Gentoo Linux 3.3.4-r1,
ssp-3.3.2-2,pie-8.7.6)
JAVA: Java(TM) 2 Runtime Environment, Standard Edition (build
Blackdown-1.4.1-01); Java HotSpot(TM) Client VM (build
Blackdown-1.4.1-01, mixed mode)
 
C

Chris Uppal

Clemens said:
I'm really in big desperation. I've never seen such strange behaviour
in any C++ or Java program before... I'm really sorry that my error
description is that long, but I don't know what to do now. Maybe
anyone has got a simple answer to one of the problems mentioned above.

From what you've described, my first thought is that you are picking up
different of the .class files somehow. Perhaps older version(s) from previous
experiments.

Anyway I don't want to spend another 8 or more hours to search for an
error I don't really know where it is...

I don't blame you. Nobody likes to do that, but sometimes that's what it
takes... :-(

-- chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,681
Members
48,796
Latest member
Greg L.

Latest Threads

Top