Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > Problems with JNI: calling a Java method from native method.

Reply
Thread Tools

Problems with JNI: calling a Java method from native method.

 
 
Jabel D. Morales - VMan of Mana
Guest
Posts: n/a
 
      08-01-2003
Hello all.

I have been experimenting with JNI to make a bridge between a Java program and
Microsoft's Tablet PC SDK (meaning C++ with Managed Extensions). So far, not
much luck.

To this moment I have had no problems to calls native methods from Java, but the
problem is whenever I try to call a Java method from the native code. This is
what I am doing so far:

The main Java class (AppDemo) initializes a set of objects for a simple Swing
program. Including is a static class member called inkStrokeCollection. The
AppDemo constructor initializes the different objects, inlcuding
inkStrokeCollection. After initializing, I make an invocation of the native
method, sending inkStrokeCollection as a parameter. This is the reason why I am
making inkStrokeCollection a static member instead of just declaring it in the
constructor.

The native method is where I have been making JNI experiments. First, I create
two Java integer arrays, one of them is returned to the AppDemo.main() which
then sends it to inkStrokeCollection.addInkStrokeWithArray(). As expected, the
Swing app is refreshed with a curve using the array as bezier control points.
The problem is when I try to send the second array directly to
inkStrokeCollection.addInkStrokeCollectionArray() from the native method. I
think I am doing the right thing. First, I am obtaining the class of the
inkStrokeCollection object which was given as a parameter to the native method.
Then, I am obtaining the method ID of
inkStrokeCollection.addInkStrokeWithArray(), which is a void method that takes
an integer array. Then, I am making a call to the method. However, the program
crashes whenever I try to do this with the following error message:

-- begin quote --
An unexpected exception has been detected in native code outside the VM.
Unexpected Signal : unknown exception code (0xe0434f4d) occurred at PC=0x77E7388
7
Function=RaiseException+0x50
Library=C:\WINDOWS\system32\kernel32.dll

Current Java thread:
at AppDemo.displayTabletCanvas(Native Method)
at AppDemo.main(AppDemo.java:55)
-- end quote --

Followed by a bunch of hexadecimal numbers and dlls.

After commenting line by line, I noticed that the crash happens whenever I do
the second step (obtaining the method id). However, I was also able to check
that the GetObjectClass function does seem to return something since the
variable containing the class ID is not NULL after calling the function.

The following are what I think are the relevant code snippets of my program:

-- begin InkStrokeCollection.java snippet --
/*
* addInkStroke
* This method adds the given InkStroke object to the ink stroke
* vector. Also, this method sends an update notification to any
* registered observers.
* Parameters:
* newInkStroke - the InkStroke object to add to the vector
* Returns:
* none.
*/
public void addInkStroke(InkStroke newInkStroke)
{
InkStrokes.add(newInkStroke);

// notifies observers
setChanged();
notifyObservers();
}

/*
* addInkStrokeWithArray
* This method adds a new InkStroke object created with the given
* integer array ink stroke vector.
* Parameters:
* intArray - the integer array to create the new InkStroke with.
* Returns:
* none.
*/
public void addInkStrokeWithArray(int[] intArray)
{
addInkStroke(new InkStroke(intArray));
}
}
-- end InkStrokeCollection.java snippet --

-- begin AppDemo.java --
[snip - imports]

public class AppDemo extends JFrame
{
// member declaration
static InkStrokeCollection inkStrokeCollection;

public static native int[] displayTabletCanvas(InkStrokeCollection
inkStrokeCollection);

static
{
System.loadLibrary("TabletCanvasManager");
}

[snip - constructor]

public static void main(String[] args)
{
// variable declaration
int[] stroke;

AppDemo appDemo = new AppDemo();
appDemo.setDefaultCloseOperation(EXIT_ON_CLOSE);
appDemo.setVisible(true);

stroke = displayTabletCanvas(inkStrokeCollection);
inkStrokeCollection.addInkStrokeWithArray(stroke);
}
}
-- end AppDemo.java --

-- begin TabletCanvasManager.cpp --
// This is the main DLL file.

[snip - includes and TabletPC SDK stuff - it works]

// second argument is jclass because of static method
// v2 - returning integer array
JNIEXPORT jintArray JNICALL Java_AppDemo_displayTabletCanvas (JNIEnv *jniEnv,
jclass appDemo, jobject inkStrokeCollection)
{
// variable declaration
jint stroke01Info[8]; // jint array containing stroke info
jintArray stroke01; // java int array for stroke
jint stroke02Info[8]; // jint array containing stroke info
jintArray stroke02; // java int array for stroke
jclass inkStrokeCollectionClass; // inkStrokeCollection class
jmethodID addInkStrokeWithArrayID; // method ID

// global variable initialization
// TabletCanvasManager *MyTabletCanvas = new TabletCanvasManager();

/*
Attempt to make call to Java application
step 1 - make a new java integer array which will contain stroke data
step 2 - call the AppDemo.inkStrokeCollection.addInkStrokeWithArray( ) method
step 3 - hope that the stroke is shown in AppDemo main window
*/

// step 1

// create data points
System::Console::WriteLine("> step 1");
stroke01Info[0] = 100;
stroke01Info[1] = 100;
stroke01Info[2] = 300;
stroke01Info[3] = 150;
stroke01Info[4] = 200;
stroke01Info[5] = 350;
stroke01Info[6] = 400;
stroke01Info[7] = 400;

stroke02Info[0] = 100;
stroke02Info[1] = 400;
stroke02Info[2] = 300;
stroke02Info[3] = 350;
stroke02Info[4] = 200;
stroke02Info[5] = 150;
stroke02Info[6] = 400;
stroke02Info[7] = 100;

// load data points to arrays
stroke01 = jniEnv->NewIntArray(;
jniEnv->SetIntArrayRegion(stroke01, 0, 8, stroke01Info);

stroke02 = jniEnv->NewIntArray(;
jniEnv->SetIntArrayRegion(stroke02, 0, 8, stroke02Info);

// step 2
System::Console::WriteLine("> step 2a");
inkStrokeCollectionClass = jniEnv->GetObjectClass(inkStrokeCollection);
System::Console::WriteLine("> step 2b");
addInkStrokeWithArrayID = jniEnv->GetMethodID(inkStrokeCollectionClass,
"addInkStrokeWithArray", "([I)V"); // <-- this is where it seems to crash
System::Console::WriteLine("> step 2c");
jniEnv->CallVoidMethod(inkStrokeCollection, addInkStrokeWithArrayID, stroke02);

return stroke01;
}
-- end TabletCanvasManager.cpp --

Any ideas? I am not sure if the reason of the crashes are because I am using
managed extensions, or because inkStrokeCollection is static. I am not sure if
its relevant, but something that I have noticed is that when it crashes, there
is no output on the console from the System::ConsoleWriteLine() calls.

System: Windows XP Pro SP1, Java 1.4.2, VisualStudio .net, TabletPC SDK

Thanks for your time.

 
Reply With Quote
 
 
 
 
Joseph Millar
Guest
Posts: n/a
 
      08-01-2003
On Fri, 01 Aug 2003 01:01:06 GMT, "Jabel D. Morales - VMan of Mana"
<(E-Mail Removed)> wrote:

> System::Console::WriteLine("> step 2a");
> inkStrokeCollectionClass = jniEnv->GetObjectClass(inkStrokeCollection);
> System::Console::WriteLine("> step 2b");
> addInkStrokeWithArrayID = jniEnv->GetMethodID(inkStrokeCollectionClass,
> "addInkStrokeWithArray", "([I)V"); // <-- this is where it seems to crash
> System::Console::WriteLine("> step 2c");
> jniEnv->CallVoidMethod(inkStrokeCollection, addInkStrokeWithArrayID, stroke02);


At first glance this all looks good, but I would guess an exception
is being raised here that you have not dealt with. No where do you
do any checking on raised Java exceptions. While I have not seen
the nt kernal api RaiseException() called in this context, it's
possible the JVM is calling it to indicate a problem. Unfortunately,
the exception code is user level code (hence starting with hex E).

I would check for exceptions after each call to a JNI routine using
ExceptionOccurred(), ExceptionDescribe() and ExceptionClear() to see
what else is going on. I suspect you will find something lurking
there. If you find no joy there, turn on your just in time debugging
in Visual Studio and verify the exact line the error is happening on
and that all your variables are as you expect them to be.

So something like this:

inkStrokeCollectionClass = jniEnv->GetObjectClass(inkStrokeCollection);
if (inkStrokeCollectionClass == NULL ||
jniEnv->ExceptionOccured())
{
// bad news, something went wrong, let's find out what
jniEnv->ExceptionDescribe()

// let the Java code handle the exception
return NULL;
}

--Joe
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
java.lang.UnsatisfiedLinkError - native method andrej.frelih@gmail.com Java 1 11-13-2007 10:18 PM
java.lang.UnsatisfiedLinkError - native method andrej.frelih@gmail.com Java 3 11-13-2007 05:45 PM
java.lang.UnsatisfiedLinkError while calling native function sonijindal@gmail.com Java 2 12-08-2006 04:26 AM
Calling the native Linux mutt module from Java... K2 Java 4 12-20-2004 08:22 PM
Java, jni.h and native method bigbinc Java 1 10-10-2003 09:27 PM



Advertisments