Java Backend

Ehc
Note: this information is now included in the source tree in text/InternalDocJazy.cltex, so this page is really obsolete.

Java Backend

IO

To do IO, the UHC standard library relies on C code which is called through the Haskell FFI. To make IO work in the Java backend without rewriting large parts of the standard library, we have two options:
  • Use the Java Native Interface (JNI) to call the C code that's also used by the other backends. This is described below.
  • Re-implement the foreign functions necessary (but not the Haskell functions using them) in Java. This is what we decided to do in UHC (as of 2010/04/20).

Using JNI for IO

To do this, we need to do the following things:
  • globally:
    • Emulate pointers in Java.We can't use real C pointers because JNI does not support "pinning" memory, and pointers become invalid after a native method call return.
    • Compile the C code used to a dynamically-linked library.
    • Load the library at runtime, using System.load(..) or System.loadLibrary(..).
  • for each function:
    • Write a wrapper method in Java.
    • Declare a native method in Java.
    • Write a wrapper function in C that calls the C function doing the real work.

As an example, here's the code needed for the write function. This assumes that there is a class uu.jazy.ehc.NativeMethods containing the native method declarations.

  • in src/jazy/uu/jazy/ehc/Prim.java:
    public static Object write(int fd, int buf, int count) {
        byte[] array = (byte[])pointers.dereference(buf);
        int result = nativeMethods.write(fd, array, count);
        return ioReturn(new Integer(result));
    }
    
  • in src/jazy/uu/jazy/ehc/NativeMethods.java:
    public native int write(int fd, byte[] buf, int count);
    
  • in C code:
    JNIEXPORT jint JNICALL Java_uu_jazy_ehc_NativeMethods_write(
            JNIEnv *env, jobject obj, jint fd, jbyteArray buf, jint count) {
        jbyte *ptr = (*env)->GetPrimitiveArrayCritical(env, buf, 0);
        int result = write(fd, ptr, count);
        (*env)->ReleasePrimitiveArrayCritical(env, buf, ptr, 0);
        return result;
    }