Using Java functions from C++ through JNI

J

jerranschmidt

Hi all,

Im wrapping some Java code in C++, i have the JVM running fine with the
correct version (1.5.0_08).

The problem comes when i call the Toolkit.getDefaultToolkit(). If i run
the java code with a test harness it runs perfect, however when i do it
with JNI it seems to just exit the function when it hits this line.

It doesnt actually return a value (not even NULL), it just terminates.

//Java
----------8<-----------
public Image getImage( String filename, byte[] imageBytes )
{
Image myToolkit = Toolkit.getDefaultToolkit().createImage( imageBytes,
0, imageBytes.length );
return myToolkit;
}
----------8<-----------


The int methods execute correctly even when the ObjectMethod
terminates.

//C++
----------8<-----------
jobject pixelBufferObject = jniEnv->CallObjectMethod( jLoadImage,
imageLoadMethodID, jstr );

int height = jniEnv->CallIntMethod( jLoadImage, getSizeYMethodID, NULL
);

int width = jniEnv->CallIntMethod( jLoadImage, getSizeXMethodID, NULL
);
----------8<-----------

Whats more is that i get no errors in compiling, linking or runtime.

I assume that the Toolkit is trying to access some sort of native
library but is not being allowed to because of the JVM for some reason.

The Java is compiled but not packaged (ie .class files not jars).

Anyone got any idea?!

Cheers!
-J
 
B

Bert Boehne

hi jerran!
what i see, is that your giving the filename to your java method through
jstr:
jobject pixelBufferObject = jniEnv->CallObjectMethod( jLoadImage,
imageLoadMethodID, jstr );
But your method also needs the parameter:
byte[] imageBytes
that parameter you are using in the following lines:
Image myToolkit = Toolkit.getDefaultToolkit().createImage( imageBytes,
0, imageBytes.length );
return myToolkit;
so i think maybe that is the fault.

greats,

bert
 
J

jerranschmidt

Bert said:
hi jerran!
what i see, is that your giving the filename to your java method through
jstr:
jobject pixelBufferObject = jniEnv->CallObjectMethod( jLoadImage,
imageLoadMethodID, jstr );
But your method also needs the parameter:
byte[] imageBytes
that parameter you are using in the following lines:
Image myToolkit = Toolkit.getDefaultToolkit().createImage( imageBytes,
0, imageBytes.length );
return myToolkit;
so i think maybe that is the fault.

greats,

bert

Hi Bert,

Sorry that is actually a method that i abstracted out of the main
method to see if it would work that way. The 'jLoadImage' method holds
the byte[] imageBytes and then calls the getImage method, passing the
imageBytes and the jstr value through to it. I think had that been the
problem the JVM wouldve crashed. This is still a very odd problem and i
cant seem to find a solution so far....

Thanks,

-J
 
C

Chris Uppal

Sorry that is actually a method that i abstracted out of the main
method to see if it would work that way.

Maybe you should post the real code then.

-- chris
 
J

jerranschmidt

Chris said:
Maybe you should post the real code then.

-- chris

Im pretty sure the rest of the code is irrelevant but here it is
anyway:

//Java

public ByteBuffer loadImage(String imagePath)
{
System.out.println("Loading texture from image: " + imagePath);
image = loadImageFromFile(imagePath);
if( image != null )
{
height = image.getHeight(null);
width = image.getWidth(null);
pixels = getImagePixels();
pixelBuffer = convertPixels();
}else{
System.out.println("Error Loading Image.");
}
System.out.println( getSizeX() );
System.out.println( getSizeY() );
return getPixelBuffer();
}

private Image loadImageFromFile( String imagePath )
{
byte[] imageBytes = getBytesFromFile( imagePath );
Image tempImage = null;
int numTries = 20;
if( imageBytes != null )
{
System.out.println(System.getProperty("java.vm.version"));
jToolkit myToolkit = new jToolkit();
tempImage = myToolkit.getImage( imagePath, imageBytes );
System.out.println("test");
while ( tempImage.getWidth(null) < 0 && numTries-- > 0 )
{
try { Thread.sleep(100); }
catch( InterruptedException x ) { System.out.println(x); }
}
while ( tempImage.getHeight(null) < 0 && numTries-- > 0 )
{
try { Thread.sleep(100); }
catch( InterruptedException x ) { System.out.println(x); }
}
}
return tempImage;
}


//abstracted java method
public Image getImage( String filename, byte[] imageBytes )
{
Image myToolkit = Toolkit.getDefaultToolkit().createImage( imageBytes,
0, imageBytes.length );
return myToolkit;
}

//c++ code
----------8<-----------
jobject pixelBufferObject = jniEnv->CallObjectMethod( jLoadImage,
imageLoadMethodID, jstr );

int height = jniEnv->CallIntMethod( jLoadImage, getSizeYMethodID, NULL
);

int width = jniEnv->CallIntMethod( jLoadImage, getSizeXMethodID, NULL
);
----------8<-----------

It is entering the java function fine and i have called other methods
to print to the screen just to verify this, but as soon as it hits the
getDefaultToolkit() it stops.
 
C

Chris Uppal

It is entering the java function fine and i have called other methods
to print to the screen just to verify this, but as soon as it hits the
getDefaultToolkit() it stops.

Ah, you previously game the impression that the application just died
(terminated) at that point. The way you say it now, it sounds as if it just
stops executing (hangs).

If so then it seems possible that you have some sort of deadlock. Asking for
the default Toolkit will cause AWT to start at least some of its internal
threads it if it hasn't already done so. If any of those threads call into
your code, and you use any kind of locking, then there's the possibility of
deadlock there. (I had exactly that problem with my own stuff when AWT was
started up).

If you remove the call to getDefaultToolkit() (and just return null from Java)
does the problem go away. Conversely if you do nothing /but/ call
getDefaultToolkit(), does the problem persist ?

I know that calling getDefaultToolkit() from a Windows app is OK, even from a
full Windows app with actual Windows, etc, because I do it myself. But (for
me) that does depend on the architectural support I have for avoiding deadlocks
from callbacks -- without that support, calling getDefaultToolkit() would hang
my application.

But if you don't have any callback hooks set, and don't define any native
methods, then I don't see how you could be experiencing deadlock. If that's
the case then I don't know what else to suggest except maybe to try invoking
getDefaultToolkit() from an action posted to the EDT thread somewhere in your
Java class's initialisation.

-- chris
 
J

jerranschmidt

Chris said:
Ah, you previously game the impression that the application just died
(terminated) at that point. The way you say it now, it sounds as if it just
stops executing (hangs).

If so then it seems possible that you have some sort of deadlock. Asking for
the default Toolkit will cause AWT to start at least some of its internal
threads it if it hasn't already done so. If any of those threads call into
your code, and you use any kind of locking, then there's the possibility of
deadlock there. (I had exactly that problem with my own stuff when AWT was
started up).

If you remove the call to getDefaultToolkit() (and just return null from Java)
does the problem go away. Conversely if you do nothing /but/ call
getDefaultToolkit(), does the problem persist ?

I know that calling getDefaultToolkit() from a Windows app is OK, even from a
full Windows app with actual Windows, etc, because I do it myself. But (for
me) that does depend on the architectural support I have for avoiding deadlocks
from callbacks -- without that support, calling getDefaultToolkit() would hang
my application.

But if you don't have any callback hooks set, and don't define any native
methods, then I don't see how you could be experiencing deadlock. If that's
the case then I don't know what else to suggest except maybe to try invoking
getDefaultToolkit() from an action posted to the EDT thread somewhere in your
Java class's initialisation.

-- chris

Hi Chris,

It doesnt actually seem to hang, it just exits the java function and
moves on with the C++. However i took your advice and tried a different
method of instantiating a Toolkit object in the constructor, this
caused the JVM to crash when running it through the JNI. So if its in
the constructor it will crash but if its inside a function it just
skips/exits (no error). This could be a deadlocking issue as you say
and this could be causing the C++ code to terminate the Java somewhat
gracefully.
Ill look into this a little further and post back if i find anything.

Thanks, problem not solved **yet**, but you have been very helpful.
Cheers,
-Jerran
 

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

Members online

Forum statistics

Threads
474,266
Messages
2,571,089
Members
48,773
Latest member
Kaybee

Latest Threads

Top