Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Use native methods to expand the Java environment

Learn how to interact with libraries and applications written in other languages

  • Print
  • Feedback

Page 4 of 7

main(int argc, char **argv ) {

jclass cls; jmethodID mid; jthrowable jthr;
/* Set up the environment */ JNI_GetDefaultJavaVMInitArgs ( &vm_args ); // Get the default arguments // Look at pages 75-76 of the JNI spec vm_args.classpath = "H:/opt/jdk/lib/classes.zip;."; // Set the classpath // equivalent to typing -classpath // on command line or setting the // environment variable JNI_CreateJavaVM(&jvm, &env, &vm_args ); // Start the VM


We also allocate some local variables to hold references to Java objects: jclass is a C reference to a Java class, jmethodID is a C reference to a Java method, and jthrowable is a C reference to Java.lang.Throwable. Page 19 of the JNI specification contains an excellent diagram that shows how to reference Java objects from C at the type level.

Next, we need to find the class we want to load.

/* Find the class we want to load */

cls = (*env)->FindClass( env, "InstantiatedFromC" );


The FindClass method causes the Java VM to search for the class specified in the second argument (in this case, InstantiatedFromC). For clarity, I have left out the check for the error condition; be sure you perform the check for cls being NULL -- in C, of course, as shown below:

if ( cls != (jclass)0 ) {


Assuming we have found the class, our next step is to get a pointer to the method we are interested in calling.

/* Find the method we want to use */
mid = (*env)->GetMethodID( env, cls, "test", "(I)I" );


It seems reasonable that you have to specify the class, the method name, and its signature. This technique simply replaces the code you would normally use for calling a method with a mechanism for doing it from C. In Java, you simply create a reference to the class, unless the method in question is static, in which case you can call it without creating an instance.

Now we are ready to call the Java method from C. The relevant portion of code in the following snippet is indicated with bold type.

/* Call the method we want to use */
printf("First call to Java returns:%d\n", (*env)->CallStaticIntMethod(env, cls, mid, 1) );
/* Check for an exception */ 
if ( hasExceptionOccurred ( env ) != (char *)0 ) {
  printf("Exception has occurred.\n");
}


The Java method we are trying to call is shown below. This method returns the input argument +1, as long as the result is not 2. If it is 2, an exception is raised.

public class InstantiatedFromC {

public int test(int number) throws Exception { System.out.println("Number from C: " + number); if ( number == 2 ) throw new Exception("Exception raised in Java seen in C"); return ( number + 1 ); } }


The code segment shown next is identical to the previous one, except that the argument we provide to the Java method is 2 instead of 1. I wanted to demonstrate how to get exception messages from Java in a C program. In this case, when the Java method returns, we call the C method that attempts to determine if there is an exception. We find that there is indeed an exception. A number of error conditions can occur while we are trying to get the exception, and it is important not to confuse these with the error condition we are trying to examine.

  • Print
  • Feedback

Resources