Sunday, March 23, 2014

Invoking the JVM via JNI on Windows with MSYS

It took me quite a few hours to get the embedding example (Chapter 7 of the JNI Programmer's Guide) to work with MinGW/MSYS.

Firstly, here's the code for invoke.c, stripped of the JDK 1.1 stuff:


/* invoke.c */

#include <stdio.h>
#include <jni.h>

#define PATH_SEPARATOR ';'
#define USER_CLASSPATH "."

int main(void) {
  JNIEnv *env;
  JavaVM *jvm;
  jint res;
  jclass class;
  jmethodID mid;
  jstring str;
  jclass stringClass;
  JavaVMInitArgs vm_args;
  JavaVMOption options[1];
  options[0].optionString = 
    "-Djava.class.path=" USER_CLASSPATH;
  vm_args.version = 0x00010002;
  vm_args.options = options;
  vm_args.nOptions = 1;
  vm_args.ignoreUnrecognized = JNI_TRUE;
  /* Create the Java VM */
  res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);


  printf("Bye.\n");

destroy:
  if ((*env)->ExceptionOccurred(env)) {
    (*env)->ExceptionDescribe(env);
  }
  (*jvm)->DestroyJavaVM(jvm);
  return 0;
}

Because the jvm.dll is name mangled you need to link to the type library jvm.lib instead (this is the bit that took me a long time to find out from web searches). So this is the command I used to compile with gcc - note I have my jdk in a folder [C:\programs] so the path doesn't have spaces:
$ gcc -D_JNI_IMPLEMENTATION -I/c/programs/java/jdk1.7.0_51/include -I/c/programs/java/jdk1.7.0_51/include/win32 invoke.c -L/c/programs/java/jdk1.7.0_51/lib -ljvm -o invoke.exe
To run I had to add the path to the "client vm" in my Bash path:
$ PATH=$PATH:/c/programs/java/jdk1.7.0_51/jre/bin/client
$ export PATH
Finally I could just run
$ ./invoke.exe

Blog Archive

About Me

My photo
Disambiguating biog as there are a few Stephen Tetley's in the world. I'm neither a cage fighter or yachtsman. I studied Fine Art in the nineties (foundation Bradford 1992, degree Cheltenham 1992 - 95) then Computing part-time at Leeds Met graduating in 2003. I'm the Stephen Tetley on Haskell Cafe and Stackoverflow.