diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -8,9 +8,11 @@
     -fno-warn-name-shadowing
  #-}
 
-import Prelude
+import Prelude hiding (catch)
 import qualified Prelude as P
 
+import Control.Exception
+
 import Data.List
 
 import Distribution.PackageDescription
@@ -38,7 +40,16 @@
     args <- getArgs
 
     args' <- case args of
-        "configure" : _ -> configure args buildOS
+        "configure" : _ -> do
+            args_ <- catch (configure args buildOS) $ \exc -> do
+                warn normal $
+                    "Could not find a JDK. Continuing anyway.\n"
+                 ++ "The error is: "
+                 ++ ((show :: SomeException -> String) exc)
+                return $
+                    args ++ ["--extra-include-dirs=./include",
+                             "--ghc-option=-optc-DFFIJNI_LIBJVM=!404!"]
+            return args_
         _ -> return args
 
     let hooks = simpleUserHooks {
@@ -175,7 +186,7 @@
     -- us where JRE and JDK are installed.
 
     javaHome <- findFirstFile id ["/usr/libexec/java_home"]
-        >>= maybe (die "Could not determine JAVA_HOME using /usr/libexec/java_home - is there a JDK installed?")
+        >>= maybe (fail "Could not determine JAVA_HOME using /usr/libexec/java_home - is there a JDK installed?")
                   return
         >>= (\cmd -> rawSystemStdout silent cmd [])
         >>= return . head . lines
@@ -195,7 +206,7 @@
     -- symlinks until we find the JDK home.
 
     javaHome <- findExecutable "javac"
-        >>= maybe (die "Could not determine path to javac.") return
+        >>= maybe (fail "Could not determine path to javac.") return
         >>= resolve >>= return . takeDirectory . takeDirectory
 
     rawSystemExit normal "javac" ["GetProperty.java"]
@@ -236,7 +247,7 @@
                       "--ghc-option=-optc-DFFIJNI_LIBJVM=" ++ libjvmPath]
 
 configure args _ = do
-
+    -- default, nothing
     return args
 
 replace :: Char -> Char -> String -> String
diff --git a/include/jni.h b/include/jni.h
new file mode 100644
--- /dev/null
+++ b/include/jni.h
@@ -0,0 +1,714 @@
+#ifndef _JNI_H_
+#define _JNI_H_
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdint.h>
+
+#define JNI_VERSION_1_1 0x00010001
+#define JNI_VERSION_1_2 0x00010002
+#define JNI_VERSION_1_4 0x00010004
+#define JNI_VERSION_1_6 0x00010006
+
+#define JNICALL
+
+#define JNI_FALSE 0
+#define JNI_TRUE  1
+
+#define JNI_OK        0
+#define JNI_ERR       (-1)
+#define JNI_EDETACHED (-2)
+#define JNI_EVERSION  (-3)
+#define JNI_ENOMEM    (-4)
+#define JNI_EEXIST    (-5)
+#define JNI_EINVAL    (-6)
+
+#define JNI_COMMIT 1
+#define JNI_ABORT  2
+
+
+typedef int8_t  jbyte;
+typedef int32_t jint;
+typedef int64_t jlong;
+
+typedef uint8_t  jboolean;
+typedef uint16_t jchar;
+typedef int16_t  jshort;
+typedef float    jfloat;
+typedef double   jdouble;
+
+typedef jint     jsize;
+
+
+struct _jobject;
+
+typedef struct _jobject *jobject;
+typedef jobject jclass;
+typedef jobject jthrowable;
+typedef jobject jstring;
+typedef jobject jarray;
+typedef jarray jbooleanArray;
+typedef jarray jbyteArray;
+typedef jarray jcharArray;
+typedef jarray jshortArray;
+typedef jarray jintArray;
+typedef jarray jlongArray;
+typedef jarray jfloatArray;
+typedef jarray jdoubleArray;
+typedef jarray jobjectArray;
+
+
+typedef jobject jweak;
+
+typedef union jvalue {
+    jboolean z;
+    jbyte    b;
+    jchar    c;
+    jshort   s;
+    jint     i;
+    jlong    j;
+    jfloat   f;
+    jdouble  d;
+    jobject  l;
+} jvalue;
+
+struct _jfieldID;
+typedef struct _jfieldID *jfieldID;
+
+struct _jmethodID;
+typedef struct _jmethodID *jmethodID;
+
+typedef enum _jobjectType {
+     JNIInvalidRefType    = 0,
+     JNILocalRefType      = 1,
+     JNIGlobalRefType     = 2,
+     JNIWeakGlobalRefType = 3
+} jobjectRefType;
+
+
+typedef struct {
+    char *name;
+    char *signature;
+    void *fnPtr;
+} JNINativeMethod;
+
+
+struct JNINativeInterface_;
+
+struct JNIEnv_;
+
+typedef const struct JNINativeInterface_ *JNIEnv;
+
+
+struct JNIInvokeInterface_;
+
+struct JavaVM_;
+
+typedef const struct JNIInvokeInterface_ *JavaVM;
+
+
+
+struct JNINativeInterface_ {
+    void *reserved0;
+    void *reserved1;
+    void *reserved2;
+
+    void *reserved3;
+    jint (JNICALL *GetVersion)(JNIEnv *env);
+
+    jclass (JNICALL *DefineClass)
+      (JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
+       jsize len);
+    jclass (JNICALL *FindClass)
+      (JNIEnv *env, const char *name);
+
+    jmethodID (JNICALL *FromReflectedMethod)
+      (JNIEnv *env, jobject method);
+    jfieldID (JNICALL *FromReflectedField)
+      (JNIEnv *env, jobject field);
+
+    jobject (JNICALL *ToReflectedMethod)
+      (JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic);
+
+    jclass (JNICALL *GetSuperclass)
+      (JNIEnv *env, jclass sub);
+    jboolean (JNICALL *IsAssignableFrom)
+      (JNIEnv *env, jclass sub, jclass sup);
+
+    jobject (JNICALL *ToReflectedField)
+      (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);
+
+    jint (JNICALL *Throw)
+      (JNIEnv *env, jthrowable obj);
+    jint (JNICALL *ThrowNew)
+      (JNIEnv *env, jclass clazz, const char *msg);
+    jthrowable (JNICALL *ExceptionOccurred)
+      (JNIEnv *env);
+    void (JNICALL *ExceptionDescribe)
+      (JNIEnv *env);
+    void (JNICALL *ExceptionClear)
+      (JNIEnv *env);
+    void (JNICALL *FatalError)
+      (JNIEnv *env, const char *msg);
+
+    jint (JNICALL *PushLocalFrame)
+      (JNIEnv *env, jint capacity);
+    jobject (JNICALL *PopLocalFrame)
+      (JNIEnv *env, jobject result);
+
+    jobject (JNICALL *NewGlobalRef)
+      (JNIEnv *env, jobject lobj);
+    void (JNICALL *DeleteGlobalRef)
+      (JNIEnv *env, jobject gref);
+    void (JNICALL *DeleteLocalRef)
+      (JNIEnv *env, jobject obj);
+    jboolean (JNICALL *IsSameObject)
+      (JNIEnv *env, jobject obj1, jobject obj2);
+    jobject (JNICALL *NewLocalRef)
+      (JNIEnv *env, jobject ref);
+    jint (JNICALL *EnsureLocalCapacity)
+      (JNIEnv *env, jint capacity);
+
+    jobject (JNICALL *AllocObject)
+      (JNIEnv *env, jclass clazz);
+    jobject (JNICALL *NewObject)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jobject (JNICALL *NewObjectV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jobject (JNICALL *NewObjectA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jclass (JNICALL *GetObjectClass)
+      (JNIEnv *env, jobject obj);
+    jboolean (JNICALL *IsInstanceOf)
+      (JNIEnv *env, jobject obj, jclass clazz);
+
+    jmethodID (JNICALL *GetMethodID)
+      (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+    jobject (JNICALL *CallObjectMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jobject (JNICALL *CallObjectMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jobject (JNICALL *CallObjectMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+    jboolean (JNICALL *CallBooleanMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jboolean (JNICALL *CallBooleanMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jboolean (JNICALL *CallBooleanMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+    jbyte (JNICALL *CallByteMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jbyte (JNICALL *CallByteMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jbyte (JNICALL *CallByteMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+    jchar (JNICALL *CallCharMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jchar (JNICALL *CallCharMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jchar (JNICALL *CallCharMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+    jshort (JNICALL *CallShortMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jshort (JNICALL *CallShortMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jshort (JNICALL *CallShortMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+    jint (JNICALL *CallIntMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jint (JNICALL *CallIntMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jint (JNICALL *CallIntMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+    jlong (JNICALL *CallLongMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jlong (JNICALL *CallLongMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jlong (JNICALL *CallLongMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+    jfloat (JNICALL *CallFloatMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jfloat (JNICALL *CallFloatMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jfloat (JNICALL *CallFloatMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+    jdouble (JNICALL *CallDoubleMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jdouble (JNICALL *CallDoubleMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jdouble (JNICALL *CallDoubleMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+    void (JNICALL *CallVoidMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    void (JNICALL *CallVoidMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    void (JNICALL *CallVoidMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+    jobject (JNICALL *CallNonvirtualObjectMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jobject (JNICALL *CallNonvirtualObjectMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jobject (JNICALL *CallNonvirtualObjectMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue * args);
+
+    jboolean (JNICALL *CallNonvirtualBooleanMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jboolean (JNICALL *CallNonvirtualBooleanMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jboolean (JNICALL *CallNonvirtualBooleanMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue * args);
+
+    jbyte (JNICALL *CallNonvirtualByteMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jbyte (JNICALL *CallNonvirtualByteMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jbyte (JNICALL *CallNonvirtualByteMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue *args);
+
+    jchar (JNICALL *CallNonvirtualCharMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jchar (JNICALL *CallNonvirtualCharMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jchar (JNICALL *CallNonvirtualCharMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue *args);
+
+    jshort (JNICALL *CallNonvirtualShortMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jshort (JNICALL *CallNonvirtualShortMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jshort (JNICALL *CallNonvirtualShortMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue *args);
+
+    jint (JNICALL *CallNonvirtualIntMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jint (JNICALL *CallNonvirtualIntMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jint (JNICALL *CallNonvirtualIntMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue *args);
+
+    jlong (JNICALL *CallNonvirtualLongMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jlong (JNICALL *CallNonvirtualLongMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jlong (JNICALL *CallNonvirtualLongMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue *args);
+
+    jfloat (JNICALL *CallNonvirtualFloatMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jfloat (JNICALL *CallNonvirtualFloatMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jfloat (JNICALL *CallNonvirtualFloatMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue *args);
+
+    jdouble (JNICALL *CallNonvirtualDoubleMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jdouble (JNICALL *CallNonvirtualDoubleMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jdouble (JNICALL *CallNonvirtualDoubleMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue *args);
+
+    void (JNICALL *CallNonvirtualVoidMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    void (JNICALL *CallNonvirtualVoidMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    void (JNICALL *CallNonvirtualVoidMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue * args);
+
+    jfieldID (JNICALL *GetFieldID)
+      (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+    jobject (JNICALL *GetObjectField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+    jboolean (JNICALL *GetBooleanField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+    jbyte (JNICALL *GetByteField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+    jchar (JNICALL *GetCharField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+    jshort (JNICALL *GetShortField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+    jint (JNICALL *GetIntField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+    jlong (JNICALL *GetLongField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+    jfloat (JNICALL *GetFloatField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+    jdouble (JNICALL *GetDoubleField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+
+    void (JNICALL *SetObjectField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val);
+    void (JNICALL *SetBooleanField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val);
+    void (JNICALL *SetByteField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val);
+    void (JNICALL *SetCharField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val);
+    void (JNICALL *SetShortField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val);
+    void (JNICALL *SetIntField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jint val);
+    void (JNICALL *SetLongField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val);
+    void (JNICALL *SetFloatField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val);
+    void (JNICALL *SetDoubleField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val);
+
+    jmethodID (JNICALL *GetStaticMethodID)
+      (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+    jobject (JNICALL *CallStaticObjectMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jobject (JNICALL *CallStaticObjectMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jobject (JNICALL *CallStaticObjectMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jboolean (JNICALL *CallStaticBooleanMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jboolean (JNICALL *CallStaticBooleanMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jboolean (JNICALL *CallStaticBooleanMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jbyte (JNICALL *CallStaticByteMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jbyte (JNICALL *CallStaticByteMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jbyte (JNICALL *CallStaticByteMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jchar (JNICALL *CallStaticCharMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jchar (JNICALL *CallStaticCharMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jchar (JNICALL *CallStaticCharMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jshort (JNICALL *CallStaticShortMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jshort (JNICALL *CallStaticShortMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jshort (JNICALL *CallStaticShortMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jint (JNICALL *CallStaticIntMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jint (JNICALL *CallStaticIntMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jint (JNICALL *CallStaticIntMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jlong (JNICALL *CallStaticLongMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jlong (JNICALL *CallStaticLongMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jlong (JNICALL *CallStaticLongMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jfloat (JNICALL *CallStaticFloatMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jfloat (JNICALL *CallStaticFloatMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jfloat (JNICALL *CallStaticFloatMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jdouble (JNICALL *CallStaticDoubleMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jdouble (JNICALL *CallStaticDoubleMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jdouble (JNICALL *CallStaticDoubleMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    void (JNICALL *CallStaticVoidMethod)
+      (JNIEnv *env, jclass cls, jmethodID methodID, ...);
+    void (JNICALL *CallStaticVoidMethodV)
+      (JNIEnv *env, jclass cls, jmethodID methodID, va_list args);
+    void (JNICALL *CallStaticVoidMethodA)
+      (JNIEnv *env, jclass cls, jmethodID methodID, const jvalue * args);
+
+    jfieldID (JNICALL *GetStaticFieldID)
+      (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+    jobject (JNICALL *GetStaticObjectField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jboolean (JNICALL *GetStaticBooleanField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jbyte (JNICALL *GetStaticByteField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jchar (JNICALL *GetStaticCharField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jshort (JNICALL *GetStaticShortField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jint (JNICALL *GetStaticIntField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jlong (JNICALL *GetStaticLongField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jfloat (JNICALL *GetStaticFloatField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jdouble (JNICALL *GetStaticDoubleField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+
+    void (JNICALL *SetStaticObjectField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value);
+    void (JNICALL *SetStaticBooleanField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value);
+    void (JNICALL *SetStaticByteField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value);
+    void (JNICALL *SetStaticCharField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value);
+    void (JNICALL *SetStaticShortField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value);
+    void (JNICALL *SetStaticIntField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value);
+    void (JNICALL *SetStaticLongField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value);
+    void (JNICALL *SetStaticFloatField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value);
+    void (JNICALL *SetStaticDoubleField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value);
+
+    jstring (JNICALL *NewString)
+      (JNIEnv *env, const jchar *unicode, jsize len);
+    jsize (JNICALL *GetStringLength)
+      (JNIEnv *env, jstring str);
+    const jchar *(JNICALL *GetStringChars)
+      (JNIEnv *env, jstring str, jboolean *isCopy);
+    void (JNICALL *ReleaseStringChars)
+      (JNIEnv *env, jstring str, const jchar *chars);
+
+    jstring (JNICALL *NewStringUTF)
+      (JNIEnv *env, const char *utf);
+    jsize (JNICALL *GetStringUTFLength)
+      (JNIEnv *env, jstring str);
+    const char* (JNICALL *GetStringUTFChars)
+      (JNIEnv *env, jstring str, jboolean *isCopy);
+    void (JNICALL *ReleaseStringUTFChars)
+      (JNIEnv *env, jstring str, const char* chars);
+
+
+    jsize (JNICALL *GetArrayLength)
+      (JNIEnv *env, jarray array);
+
+    jobjectArray (JNICALL *NewObjectArray)
+      (JNIEnv *env, jsize len, jclass clazz, jobject init);
+    jobject (JNICALL *GetObjectArrayElement)
+      (JNIEnv *env, jobjectArray array, jsize index);
+    void (JNICALL *SetObjectArrayElement)
+      (JNIEnv *env, jobjectArray array, jsize index, jobject val);
+
+    jbooleanArray (JNICALL *NewBooleanArray)
+      (JNIEnv *env, jsize len);
+    jbyteArray (JNICALL *NewByteArray)
+      (JNIEnv *env, jsize len);
+    jcharArray (JNICALL *NewCharArray)
+      (JNIEnv *env, jsize len);
+    jshortArray (JNICALL *NewShortArray)
+      (JNIEnv *env, jsize len);
+    jintArray (JNICALL *NewIntArray)
+      (JNIEnv *env, jsize len);
+    jlongArray (JNICALL *NewLongArray)
+      (JNIEnv *env, jsize len);
+    jfloatArray (JNICALL *NewFloatArray)
+      (JNIEnv *env, jsize len);
+    jdoubleArray (JNICALL *NewDoubleArray)
+      (JNIEnv *env, jsize len);
+
+    jboolean * (JNICALL *GetBooleanArrayElements)
+      (JNIEnv *env, jbooleanArray array, jboolean *isCopy);
+    jbyte * (JNICALL *GetByteArrayElements)
+      (JNIEnv *env, jbyteArray array, jboolean *isCopy);
+    jchar * (JNICALL *GetCharArrayElements)
+      (JNIEnv *env, jcharArray array, jboolean *isCopy);
+    jshort * (JNICALL *GetShortArrayElements)
+      (JNIEnv *env, jshortArray array, jboolean *isCopy);
+    jint * (JNICALL *GetIntArrayElements)
+      (JNIEnv *env, jintArray array, jboolean *isCopy);
+    jlong * (JNICALL *GetLongArrayElements)
+      (JNIEnv *env, jlongArray array, jboolean *isCopy);
+    jfloat * (JNICALL *GetFloatArrayElements)
+      (JNIEnv *env, jfloatArray array, jboolean *isCopy);
+    jdouble * (JNICALL *GetDoubleArrayElements)
+      (JNIEnv *env, jdoubleArray array, jboolean *isCopy);
+
+    void (JNICALL *ReleaseBooleanArrayElements)
+      (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode);
+    void (JNICALL *ReleaseByteArrayElements)
+      (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode);
+    void (JNICALL *ReleaseCharArrayElements)
+      (JNIEnv *env, jcharArray array, jchar *elems, jint mode);
+    void (JNICALL *ReleaseShortArrayElements)
+      (JNIEnv *env, jshortArray array, jshort *elems, jint mode);
+    void (JNICALL *ReleaseIntArrayElements)
+      (JNIEnv *env, jintArray array, jint *elems, jint mode);
+    void (JNICALL *ReleaseLongArrayElements)
+      (JNIEnv *env, jlongArray array, jlong *elems, jint mode);
+    void (JNICALL *ReleaseFloatArrayElements)
+      (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode);
+    void (JNICALL *ReleaseDoubleArrayElements)
+      (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode);
+
+    void (JNICALL *GetBooleanArrayRegion)
+      (JNIEnv *env, jbooleanArray array, jsize start, jsize l, jboolean *buf);
+    void (JNICALL *GetByteArrayRegion)
+      (JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf);
+    void (JNICALL *GetCharArrayRegion)
+      (JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf);
+    void (JNICALL *GetShortArrayRegion)
+      (JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf);
+    void (JNICALL *GetIntArrayRegion)
+      (JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf);
+    void (JNICALL *GetLongArrayRegion)
+      (JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf);
+    void (JNICALL *GetFloatArrayRegion)
+      (JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf);
+    void (JNICALL *GetDoubleArrayRegion)
+      (JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf);
+
+    void (JNICALL *SetBooleanArrayRegion)
+      (JNIEnv *env, jbooleanArray array, jsize start, jsize l, const jboolean *buf);
+    void (JNICALL *SetByteArrayRegion)
+      (JNIEnv *env, jbyteArray array, jsize start, jsize len, const jbyte *buf);
+    void (JNICALL *SetCharArrayRegion)
+      (JNIEnv *env, jcharArray array, jsize start, jsize len, const jchar *buf);
+    void (JNICALL *SetShortArrayRegion)
+      (JNIEnv *env, jshortArray array, jsize start, jsize len, const jshort *buf);
+    void (JNICALL *SetIntArrayRegion)
+      (JNIEnv *env, jintArray array, jsize start, jsize len, const jint *buf);
+    void (JNICALL *SetLongArrayRegion)
+      (JNIEnv *env, jlongArray array, jsize start, jsize len, const jlong *buf);
+    void (JNICALL *SetFloatArrayRegion)
+      (JNIEnv *env, jfloatArray array, jsize start, jsize len, const jfloat *buf);
+    void (JNICALL *SetDoubleArrayRegion)
+      (JNIEnv *env, jdoubleArray array, jsize start, jsize len, const jdouble *buf);
+
+    jint (JNICALL *RegisterNatives)
+      (JNIEnv *env, jclass clazz, const JNINativeMethod *methods,
+       jint nMethods);
+    jint (JNICALL *UnregisterNatives)
+      (JNIEnv *env, jclass clazz);
+
+    jint (JNICALL *MonitorEnter)
+      (JNIEnv *env, jobject obj);
+    jint (JNICALL *MonitorExit)
+      (JNIEnv *env, jobject obj);
+
+    jint (JNICALL *GetJavaVM)
+      (JNIEnv *env, JavaVM **vm);
+
+    void (JNICALL *GetStringRegion)
+      (JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);
+    void (JNICALL *GetStringUTFRegion)
+      (JNIEnv *env, jstring str, jsize start, jsize len, char *buf);
+
+    void * (JNICALL *GetPrimitiveArrayCritical)
+      (JNIEnv *env, jarray array, jboolean *isCopy);
+    void (JNICALL *ReleasePrimitiveArrayCritical)
+      (JNIEnv *env, jarray array, void *carray, jint mode);
+
+    const jchar * (JNICALL *GetStringCritical)
+      (JNIEnv *env, jstring string, jboolean *isCopy);
+    void (JNICALL *ReleaseStringCritical)
+      (JNIEnv *env, jstring string, const jchar *cstring);
+
+    jweak (JNICALL *NewWeakGlobalRef)
+       (JNIEnv *env, jobject obj);
+    void (JNICALL *DeleteWeakGlobalRef)
+       (JNIEnv *env, jweak ref);
+
+    jboolean (JNICALL *ExceptionCheck)
+       (JNIEnv *env);
+
+    jobject (JNICALL *NewDirectByteBuffer)
+       (JNIEnv* env, void* address, jlong capacity);
+    void* (JNICALL *GetDirectBufferAddress)
+       (JNIEnv* env, jobject buf);
+    jlong (JNICALL *GetDirectBufferCapacity)
+       (JNIEnv* env, jobject buf);
+
+    jobjectRefType (JNICALL *GetObjectRefType)
+        (JNIEnv* env, jobject obj);
+};
+
+
+struct JNIEnv_ {
+    const struct JNINativeInterface_ *functions;
+};
+
+
+typedef struct JavaVMOption {
+    char *optionString;
+    void *extraInfo;
+} JavaVMOption;
+
+typedef struct JavaVMInitArgs {
+    jint version;
+
+    jint nOptions;
+    JavaVMOption *options;
+    jboolean ignoreUnrecognized;
+} JavaVMInitArgs;
+
+typedef struct JavaVMAttachArgs {
+    jint version;
+
+    char *name;
+    jobject group;
+} JavaVMAttachArgs;
+
+
+struct JNIInvokeInterface_ {
+    void *reserved0;
+    void *reserved1;
+    void *reserved2;
+
+    jint (JNICALL *DestroyJavaVM)(JavaVM *vm);
+
+    jint (JNICALL *AttachCurrentThread)(JavaVM *vm, void **penv, void *args);
+
+    jint (JNICALL *DetachCurrentThread)(JavaVM *vm);
+
+    jint (JNICALL *GetEnv)(JavaVM *vm, void **penv, jint version);
+
+    jint (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM *vm, void **penv, void *args);
+};
+
+struct JavaVM_ {
+    const struct JNIInvokeInterface_ *functions;
+};
+
+#endif /*_JNI_H_*/
+
+
diff --git a/java-bridge.cabal b/java-bridge.cabal
--- a/java-bridge.cabal
+++ b/java-bridge.cabal
@@ -1,5 +1,5 @@
 name:           java-bridge
-version:        0.20130602
+version:        0.20130606
 
 license:        MIT
 license-file:   LICENSE
@@ -13,64 +13,71 @@
 cabal-version:  >= 1.8
 
 synopsis:       Bindings to the JNI and a high level interface generator.
-description:    This package offers bindings to the /Java Native Interface/
-                and a high level interface generator.
+description:    This package offers bindings to the
+                /Java Native Interface/ and a high level interface
+                generator.
                 .
                 [@low level bindings to the JNI@]
-                    The low level bindings are located in "Foreign.Java.JNI.Safe"
-                    and "Foreign.Java.JNI.Unsafe". When using these bindings you
-                    will have to deal with pointers and manage global references
-                    manually.
+                    The low level bindings are located in
+                    "Foreign.Java.JNI.Safe" and "Foreign.Java.JNI.Unsafe".
+                    When using these bindings you will have to deal with
+                    pointers and manage global references manually.
                 .
                 [@medium level interface@]
-                    The medium level interface is located in "Foreign.Java".
-                    It offers an abstraction over the JNI, i.e. you will not
-                    have to deal with pointers explicitly nor do you need to
-                    manually do conversions between native types and Haskell
-                    types. Also references will automatically be released by
-                    the Haskell runtime when no longer needed. You will still
-                    need to manually lookup classes and methods in order to use
-                    them.
+                    The medium level interface is located in
+                    "Foreign.Java". It offers an abstraction over the JNI,
+                    i.e. you will not have to deal with pointers
+                    explicitly nor do you need to manually do conversions
+                    between native types and Haskell types.
+                    Also references will automatically be released by
+                    the Haskell runtime when no longer needed. You will
+                    still need to manually lookup classes and methods in
+                    order to use them.
                 .
                 [@high level bindings generator@]
-                    You can also generate high level bindings using the tools
-                    @j2hs@ and @hs2j@ that come along with this package. The tools
-                    works in both directions, i.e. you can generate glue code to use
-                    existing Java libraries from within Haskell as well as to use
-                    Haskell from within Java. This is the most convenient way
-                    to deal with a Java library.
+                    You can also generate high level bindings using the
+                    tools @j2hs@ and @hs2j@ that come along with this
+                    package. The tools works in both directions, i.e. you
+                    can generate glue code to use existing Java libraries
+                    from within Haskell as well as to use Haskell from
+                    within Java. This is the most convenient way to deal
+                    with a Java library.
                 .
                 .
                 >>> INSTALLATION / USAGE
                 .
                 It should suffice to do @cabal install@ (or
-                @cabal install java-bridge@ when installing from hackageDB).
-                /You need to have a JDK installed prior to installing this library/.
+                @cabal install java-bridge@ when installing from
+                hackageDB). /You need to have a JDK installed prior to
+                installing this library/.
                 .
-                Setup will try to find the location of your java installation
-                automatically. This is needed in order to load @libjvm@.
-                Note that this library is loaded dynamically, which
-                means that linking errors might not show up during installation.
+                Setup will try to find the location of your java
+                installation automatically. This is needed in order to
+                load @libjvm@. Note that this library is loaded
+                dynamically, which  means that linking errors might not
+                show up during installation.
                 .
-                You can specify the location of @libjvm@ manually using the
-                environment variable @FFIJNI_LIBJVM@. This environment variable
-                is consulted by @Setup.hs@ as well as by the library each time
-                @libjvm@ is loaded - which means that you can override the path to
-                @libjvm@ at any time. The function @getCompiledLibjvmPath@ in
-                "Foreign.Java.JNI.Safe" will tell you what path to @libjvm@ has
-                been set during compilation of the library.
+                You can specify the location of @libjvm@ manually using
+                the environment variable @FFIJNI_LIBJVM@. This
+                environment variable is consulted by @Setup.hs@ as well
+                as by the library each time @libjvm@ is loaded - which
+                means that you can override the path to @libjvm@ at any
+                time. The function @getCompiledLibjvmPath@ in
+                "Foreign.Java.JNI.Safe" will tell you what path to
+                @libjvm@ has been set during compilation of the library.
                 .
                 .
                 >>> FUN WITH (cabal-) FLAGS
                 .
-                The following cabal flags are available to you for configuring
-                your installation:
+                The following cabal flags are available to you for
+                configuring your installation:
                 .
                 [@ONLY_CORE@]
                     Build only the Core Modules which offer a
                     direct binding to the Java Native Interface.
                     The core modules are "Foreign.Java.JNI",
-                    "Foreign.Java.JNI.Safe", and "Foreign.Java.JNI.Unsafe".
+                    "Foreign.Java.JNI.Safe",
+                    and "Foreign.Java.JNI.Unsafe".
                     This implies @NO_TOOLS@.
                     Defaults to @False@.
                 .
@@ -98,7 +105,8 @@
                     with @java-@ and located along your haskell
                     executables. Defaults to @False@.
                 .
-                Use for example @cabal install -f OSX_FRAMEWORK -f EXAMPLES@
+                Use for example
+                @cabal install -f OSX_FRAMEWORK -f EXAMPLES@
                 or @cabal configure -f DEBUG@.
                 .
                 .
@@ -108,7 +116,8 @@
                 
 build-type:     Custom
 
-extra-source-files: src/Foreign/Java/JNI/core.hs,
+extra-source-files: include/jni.h,
+                    src/Foreign/Java/JNI/core.hs,
                     src/ffijni.h,
                     GetProperty.java,
                     examples/calculator/calculator.cabal,
@@ -146,8 +155,8 @@
 
 
 Library
-    cc-options:         -DFFIJNI_BRIDGE_VERSION="0.20130602"
-    cpp-options:        -DFFIJNI_BRIDGE_VERSION="0.20130602"
+    cc-options:         -DFFIJNI_BRIDGE_VERSION="0.20130606"
+    cpp-options:        -DFFIJNI_BRIDGE_VERSION="0.20130606"
 
     build-depends:      base >= 4.5 && < 5
                         , directory >= 1.1.0.2
@@ -235,14 +244,6 @@
 
 
 Executable j2hs
-    if flag(ONLY_CORE)
-        buildable: False
-    else
-        if flag(NO_TOOLS)
-            buildable: False
-        else
-            buildable: True
-
     hs-source-dirs: j2hs
     main-is: Main.hs
 
@@ -252,25 +253,7 @@
 
     build-depends:  base >= 4.5 && < 5
                     , java-bridge
-                    -- The following are part of the GHC core packages:
-                    , containers >= 0.4.2.1
-                    , directory >= 1.1.0.2
-                    , filepath >= 1.3
-                    -- These are part of the Haskell Platform:
-                    , syb >= 0.3.6.1
-                    , split >= 0.2.1.1
-                    -- These are available from HackageDB:
-                    , strings >= 1.1
-                    , multimap >= 1.2
-                    , names >= 0.3.1 && < 0.4
-                    , named-records >= 0.5
-                    -- These are also available form HackageDB but from
-                    -- another maintainer than this package:
-                    , bimap >= 0.2.4
-                    , hint >= 0.3.3.4
 
-
-Executable h2js
     if flag(ONLY_CORE)
         buildable: False
     else
@@ -278,7 +261,22 @@
             buildable: False
         else
             buildable: True
+            build-depends:  containers >= 0.4.2.1
+                            , directory >= 1.1.0.2
+                            , filepath >= 1.3
+                            -- These are part of the Haskell Platform:
+                            , syb >= 0.3.6.1
+                            , split >= 0.2.1.1
+                            -- These are available from HackageDB:
+                            , strings >= 1.1
+                            , multimap >= 1.2
+                            , names >= 0.3.1 && < 0.4
+                            , named-records >= 0.5
+                            , bimap >= 0.2.4
+                            , hint >= 0.3.3.4
 
+
+Executable h2js
     hs-source-dirs: hs2j
     main-is: Main.hs
 
@@ -288,22 +286,27 @@
 
     build-depends:  base >= 4.5 && < 5
                     , java-bridge
-                    -- The following are part of the GHC core packages:
-                    , containers >= 0.4.2.1
-                    , directory >= 1.1.0.2
-                    , filepath >= 1.3
-                    -- These are part of the Haskell Platform:
-                    , syb >= 0.3.6.1
-                    , split >= 0.2.1.1
-                    -- These are available from HackageDB:
-                    , strings >= 1.1
-                    , multimap >= 1.1
-                    , names >= 0.3.1 && < 0.4
-                    , named-records >= 0.5
-                    -- These are also available form HackageDB but from
-                    -- another maintainer than this package:
-                    , bimap >= 0.2.4
-                    , hint >= 0.3.3.4
+
+    if flag(ONLY_CORE)
+        buildable: False
+    else
+        if flag(NO_TOOLS)
+            buildable: False
+        else
+            buildable: True
+            build-depends: containers >= 0.4.2.1
+                           , directory >= 1.1.0.2
+                           , filepath >= 1.3
+                           -- These are part of the Haskell Platform:
+                           , syb >= 0.3.6.1
+                           , split >= 0.2.1.1
+                           -- These are available from HackageDB:
+                           , strings >= 1.1
+                           , multimap >= 1.1
+                           , names >= 0.3.1 && < 0.4
+                           , named-records >= 0.5
+                           , bimap >= 0.2.4
+                           , hint >= 0.3.3.4
 
 
 Executable java-calculator
