diff --git a/jni.cabal b/jni.cabal
--- a/jni.cabal
+++ b/jni.cabal
@@ -1,5 +1,5 @@
 name:                jni
-version:             0.2
+version:             0.2.1
 synopsis:            Complete JNI raw bindings.
 description:         Please see README.md.
 homepage:            https://github.com/tweag/inline-java/tree/master/jni#readme
@@ -29,6 +29,8 @@
     Foreign.JNI
     Foreign.JNI.Types
     Foreign.JNI.String
+  other-modules:
+    Foreign.JNI.NativeMethod
   build-depends:
     base >= 4.7 && < 5,
     bytestring >=0.10,
diff --git a/src/Foreign/JNI.c b/src/Foreign/JNI.c
--- a/src/Foreign/JNI.c
+++ b/src/Foreign/JNI.c
@@ -75,12 +75,36 @@
 }
 
 
-jclass inline_c_Foreign_JNI_7_98f2efdfb85a70a64012d4a321b2e1b53ec6d783(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, char * namep_inline_c_2) {
+jint inline_c_Foreign_JNI_7_b2b4b4a025c54c183ac34fda20ed77aaa1cbd6ed(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, JNINativeMethod * cmethods_inline_c_3, int numMethods_inline_c_4) {
+return (
+             (*env_inline_c_0)->RegisterNatives(env_inline_c_1,
+                                                cls_inline_c_2,
+                                                cmethods_inline_c_3,
+                                                numMethods_inline_c_4) );
+}
+
+
+jint inline_c_Foreign_JNI_8_7da57142503fa6323136b7c159710e69a3507ecd(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2) {
+return (
+       (*env_inline_c_0)->Throw(env_inline_c_1,
+                                obj_inline_c_2) );
+}
+
+
+jint inline_c_Foreign_JNI_9_28bfcee12881af1c4a1c7de9b19c8263659c32d9(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, char * msgp_inline_c_3) {
+return (
+       (*env_inline_c_0)->ThrowNew(env_inline_c_1,
+                                   cls_inline_c_2,
+                                   msgp_inline_c_3) );
+}
+
+
+jclass inline_c_Foreign_JNI_10_98f2efdfb85a70a64012d4a321b2e1b53ec6d783(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, char * namep_inline_c_2) {
 return ( (*env_inline_c_0)->FindClass(env_inline_c_1, namep_inline_c_2) );
 }
 
 
-jobject inline_c_Foreign_JNI_8_db79f2d25dd672f2593a68b078850f23bf59b54d(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID constr_inline_c_3, jvalue * cargs_inline_c_4) {
+jobject inline_c_Foreign_JNI_11_db79f2d25dd672f2593a68b078850f23bf59b54d(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID constr_inline_c_3, jvalue * cargs_inline_c_4) {
 return (
         (*env_inline_c_0)->NewObjectA(env_inline_c_1,
                                       cls_inline_c_2,
@@ -89,7 +113,7 @@
 }
 
 
-jfieldID inline_c_Foreign_JNI_9_24f9a5b843f700dd367457745083b0f737727165(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, char * fieldnamep_inline_c_3, char * sigp_inline_c_4) {
+jfieldID inline_c_Foreign_JNI_12_24f9a5b843f700dd367457745083b0f737727165(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, char * fieldnamep_inline_c_3, char * sigp_inline_c_4) {
 return (
       (*env_inline_c_0)->GetFieldID(env_inline_c_1,
                                     cls_inline_c_2,
@@ -98,7 +122,7 @@
 }
 
 
-jfieldID inline_c_Foreign_JNI_10_7f51c9e3dfc10d19fa55f2bad6ee5d30c55df36e(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, char * fieldnamep_inline_c_3, char * sigp_inline_c_4) {
+jfieldID inline_c_Foreign_JNI_13_7f51c9e3dfc10d19fa55f2bad6ee5d30c55df36e(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, char * fieldnamep_inline_c_3, char * sigp_inline_c_4) {
 return (
       (*env_inline_c_0)->GetStaticFieldID(env_inline_c_1,
                                           cls_inline_c_2,
@@ -107,32 +131,187 @@
 }
 
 
-jobject inline_c_Foreign_JNI_11_fd81942890ffe8025c7c8e605b29bfa2d631bf64(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3) {
-return (
-      (*env_inline_c_0)->GetObjectField(env_inline_c_1,
-                                        obj_inline_c_2,
-                                        field_inline_c_3) );
+jobject inline_c_Foreign_JNI_14_d3bbd4f49ae66a171a74a554b1ad29de1e653fbe(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetObjectField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3) );
 }
 
 
-jobject inline_c_Foreign_JNI_12_1a61c240cf989921cf3de3040c147f73e14adeda(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3) {
-return (
-      (*env_inline_c_0)->GetStaticObjectField(env_inline_c_1,
-                                              klass_inline_c_2,
-                                              field_inline_c_3) );
+jboolean inline_c_Foreign_JNI_15_a6c318bded4eb76e31688bb79797fe16d6ad53cd(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetBooleanField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3) );
 }
 
 
-void inline_c_Foreign_JNI_13_afa80a9b59e6bbc9bb12dee01bee2f7e93eefcae(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3, jboolean b_inline_c_4) {
+jbyte inline_c_Foreign_JNI_16_ce49e2a35bd9168e5441c414c23484ab5ed3bfd1(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetByteField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3) );
+}
 
-      (*env_inline_c_0)->SetBooleanField(env_inline_c_1,
-                                        obj_inline_c_2,
-                                        field_inline_c_3,
-                                        b_inline_c_4); 
+
+jchar inline_c_Foreign_JNI_17_c943f6f26c7dc18be8ee2dbae90e076a32d0bc7b(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetCharField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3) );
 }
 
 
-jmethodID inline_c_Foreign_JNI_14_e722a7a0d6891db8a6cda0ec21cc6312aaeec3c0(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, char * methodnamep_inline_c_3, char * sigp_inline_c_4) {
+jshort inline_c_Foreign_JNI_18_4f9206f7afb17d7f7a4ca9c25e5e6ed84e09389c(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetShortField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3) );
+}
+
+
+jint inline_c_Foreign_JNI_19_0163f5dc997937b24f9a57dbb7fac4a42db7f087(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetIntField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3) );
+}
+
+
+jlong inline_c_Foreign_JNI_20_46309075736c07065202cd83573f912c5501b005(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetLongField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3) );
+}
+
+
+jfloat inline_c_Foreign_JNI_21_2c66977fbc363fd8fb05ce6ab75fd556531d5a17(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetFloatField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3) );
+}
+
+
+jdouble inline_c_Foreign_JNI_22_272ef095b5f25c1f0f9482e390b6a782adff8c47(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetDoubleField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3) );
+}
+
+
+jobject inline_c_Foreign_JNI_23_5c71747967eb4276bca3e20b379750babbebda8e(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetStaticObjectField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3) );
+}
+
+
+jboolean inline_c_Foreign_JNI_24_b176fa5abc4a517382107db7f9cf6e9d39f42790(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetStaticBooleanField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3) );
+}
+
+
+jbyte inline_c_Foreign_JNI_25_27a626282a93b144decfac0d91b1620bd593f9b3(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetStaticByteField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3) );
+}
+
+
+jchar inline_c_Foreign_JNI_26_a04d9bdb806b0e16000ef35f7159e5dd16b3dd70(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetStaticCharField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3) );
+}
+
+
+jshort inline_c_Foreign_JNI_27_5bbf8ff1a31ec47edf1a6f51423acec6a8c165d9(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetStaticShortField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3) );
+}
+
+
+jint inline_c_Foreign_JNI_28_e412724b75f372f7be355611dc8047fb9ae1126b(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetStaticIntField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3) );
+}
+
+
+jlong inline_c_Foreign_JNI_29_89d32b3c2be6d4e4e01285d42a1845567da8d5ef(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetStaticLongField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3) );
+}
+
+
+jfloat inline_c_Foreign_JNI_30_fb5c2b1d3de9b233f712bd7c5d5e38deb356b1e9(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetStaticFloatField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3) );
+}
+
+
+jdouble inline_c_Foreign_JNI_31_492512f55c5b7ee515200d9a8a08009e7788aa22(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3) {
+return (       (*env_inline_c_0)->GetStaticDoubleField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3) );
+}
+
+
+void inline_c_Foreign_JNI_32_584abfc1ea057f29617db577aa8a7bcf87c50277(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3, jobject x_inline_c_4) {
+       (*env_inline_c_0)->SetObjectField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3,                                               x_inline_c_4); 
+}
+
+
+void inline_c_Foreign_JNI_33_d740752f4e956bdbcfdeb49ad9c4daac79454740(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3, jboolean x_inline_c_4) {
+       (*env_inline_c_0)->SetBooleanField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3,                                               x_inline_c_4); 
+}
+
+
+void inline_c_Foreign_JNI_34_7c7e899dc92453c6973878ad7b630dca1101ec2f(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3, jbyte x_inline_c_4) {
+       (*env_inline_c_0)->SetByteField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3,                                               x_inline_c_4); 
+}
+
+
+void inline_c_Foreign_JNI_35_77351519d67b4f4ab49c6b1dc32a190a8f7a2524(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3, jchar x_inline_c_4) {
+       (*env_inline_c_0)->SetCharField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3,                                               x_inline_c_4); 
+}
+
+
+void inline_c_Foreign_JNI_36_cbc8c11ddfd08b4a88953c743e6ea91feb0ac607(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3, jshort x_inline_c_4) {
+       (*env_inline_c_0)->SetShortField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3,                                               x_inline_c_4); 
+}
+
+
+void inline_c_Foreign_JNI_37_f318d1d52db33d7bf0dc7e5c6e9e0a71484ecb5d(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3, jint x_inline_c_4) {
+       (*env_inline_c_0)->SetIntField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3,                                               x_inline_c_4); 
+}
+
+
+void inline_c_Foreign_JNI_38_0d005c04266d114f3826b408c1b80edae3cd0fe9(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3, jlong x_inline_c_4) {
+       (*env_inline_c_0)->SetLongField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3,                                               x_inline_c_4); 
+}
+
+
+void inline_c_Foreign_JNI_39_6a8a9ce4e7e8acae90231495db2fd8854b488d5d(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3, jfloat x_inline_c_4) {
+       (*env_inline_c_0)->SetFloatField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3,                                               x_inline_c_4); 
+}
+
+
+void inline_c_Foreign_JNI_40_c3947546832da8a398f347c27908ee58b78f6b9d(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jfieldID field_inline_c_3, jdouble x_inline_c_4) {
+       (*env_inline_c_0)->SetDoubleField(env_inline_c_1,                                               obj_inline_c_2,                                               field_inline_c_3,                                               x_inline_c_4); 
+}
+
+
+void inline_c_Foreign_JNI_41_b84acff3f2e26a2a2d4e3f2a7fa46cdfbc099912(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3, jobject x_inline_c_4) {
+       (*env_inline_c_0)->SetStaticObjectField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3,                                                     x_inline_c_4); 
+}
+
+
+void inline_c_Foreign_JNI_42_a02725e5169b86b9c1c527aaf96872a055940707(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3, jboolean x_inline_c_4) {
+       (*env_inline_c_0)->SetStaticBooleanField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3,                                                     x_inline_c_4); 
+}
+
+
+void inline_c_Foreign_JNI_43_a3232ebc0e49f3217ef3dd1bce52bbb83462aede(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3, jbyte x_inline_c_4) {
+       (*env_inline_c_0)->SetStaticByteField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3,                                                     x_inline_c_4); 
+}
+
+
+void inline_c_Foreign_JNI_44_6e323e9e26073d2c2b53ede3444cdf73ce5b4aad(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3, jchar x_inline_c_4) {
+       (*env_inline_c_0)->SetStaticCharField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3,                                                     x_inline_c_4); 
+}
+
+
+void inline_c_Foreign_JNI_45_f6cfa9b49f03261d0c67c68fb9595a818e3e28cb(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3, jshort x_inline_c_4) {
+       (*env_inline_c_0)->SetStaticShortField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3,                                                     x_inline_c_4); 
+}
+
+
+void inline_c_Foreign_JNI_46_f382d7603879ddb1eca55b052c49ed4b418e2cc7(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3, jint x_inline_c_4) {
+       (*env_inline_c_0)->SetStaticIntField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3,                                                     x_inline_c_4); 
+}
+
+
+void inline_c_Foreign_JNI_47_02c96789057bffbad5c0921c8e94f8ffc7f6a392(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3, jlong x_inline_c_4) {
+       (*env_inline_c_0)->SetStaticLongField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3,                                                     x_inline_c_4); 
+}
+
+
+void inline_c_Foreign_JNI_48_2f1ae23c6909cb66e439ed94bb49a5b5b117268c(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3, jfloat x_inline_c_4) {
+       (*env_inline_c_0)->SetStaticFloatField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3,                                                     x_inline_c_4); 
+}
+
+
+void inline_c_Foreign_JNI_49_3f17c8ae6483640141674f2ae41409e830a60690(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass klass_inline_c_2, jfieldID field_inline_c_3, jdouble x_inline_c_4) {
+       (*env_inline_c_0)->SetStaticDoubleField(env_inline_c_1,                                                     klass_inline_c_2,                                                     field_inline_c_3,                                                     x_inline_c_4); 
+}
+
+
+jmethodID inline_c_Foreign_JNI_50_e722a7a0d6891db8a6cda0ec21cc6312aaeec3c0(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, char * methodnamep_inline_c_3, char * sigp_inline_c_4) {
 return (
       (*env_inline_c_0)->GetMethodID(env_inline_c_1,
                                      cls_inline_c_2,
@@ -141,7 +320,7 @@
 }
 
 
-jmethodID inline_c_Foreign_JNI_15_196e9055f6891bfa3cf856c108612c9572ecc877(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, char * methodnamep_inline_c_3, char * sigp_inline_c_4) {
+jmethodID inline_c_Foreign_JNI_51_196e9055f6891bfa3cf856c108612c9572ecc877(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, char * methodnamep_inline_c_3, char * sigp_inline_c_4) {
 return (
       (*env_inline_c_0)->GetStaticMethodID(env_inline_c_1,
                                            cls_inline_c_2,
@@ -150,107 +329,114 @@
 }
 
 
-void inline_c_Foreign_JNI_16_1fc0f64f3f314012d49ffbd906fd558d03aef37d(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jclass inline_c_Foreign_JNI_52_9f847198f949d76076adbd2e63e17b2ed0e73c41(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2) {
+return (
+      (*env_inline_c_0)->GetObjectClass(env_inline_c_1,
+                                        obj_inline_c_2) );
+}
+
+
+void inline_c_Foreign_JNI_53_1fc0f64f3f314012d49ffbd906fd558d03aef37d(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
        (*env_inline_c_0)->CallVoidMethodA(env_inline_c_1,                                                obj_inline_c_2,                                                method_inline_c_3,                                                cargs_inline_c_4) ;
 }
 
 
-jobject inline_c_Foreign_JNI_17_203a086f6ff15893a2417732fde0904a88dd4307(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jobject inline_c_Foreign_JNI_54_203a086f6ff15893a2417732fde0904a88dd4307(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallObjectMethodA(env_inline_c_1,                                                obj_inline_c_2,                                                method_inline_c_3,                                                cargs_inline_c_4) );
 }
 
 
-jboolean inline_c_Foreign_JNI_18_b729da20539bd62f9d8b8e8579dbf42bbafc76c4(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jboolean inline_c_Foreign_JNI_55_b729da20539bd62f9d8b8e8579dbf42bbafc76c4(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallBooleanMethodA(env_inline_c_1,                                                obj_inline_c_2,                                                method_inline_c_3,                                                cargs_inline_c_4) );
 }
 
 
-jbyte inline_c_Foreign_JNI_19_4e4bdbfc154de6ffe6eb562e1edfcbb529c275e8(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jbyte inline_c_Foreign_JNI_56_4e4bdbfc154de6ffe6eb562e1edfcbb529c275e8(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallByteMethodA(env_inline_c_1,                                                obj_inline_c_2,                                                method_inline_c_3,                                                cargs_inline_c_4) );
 }
 
 
-jchar inline_c_Foreign_JNI_20_5e000da030371e4db09c808934e3e5f504eda6c9(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jchar inline_c_Foreign_JNI_57_5e000da030371e4db09c808934e3e5f504eda6c9(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallCharMethodA(env_inline_c_1,                                                obj_inline_c_2,                                                method_inline_c_3,                                                cargs_inline_c_4) );
 }
 
 
-jshort inline_c_Foreign_JNI_21_516aded3c2f638c87a12e56d246bdcea1c7e1a47(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jshort inline_c_Foreign_JNI_58_516aded3c2f638c87a12e56d246bdcea1c7e1a47(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallShortMethodA(env_inline_c_1,                                                obj_inline_c_2,                                                method_inline_c_3,                                                cargs_inline_c_4) );
 }
 
 
-jint inline_c_Foreign_JNI_22_58b123994733ee132cc23af0e5a7da34ef37f584(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jint inline_c_Foreign_JNI_59_58b123994733ee132cc23af0e5a7da34ef37f584(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallIntMethodA(env_inline_c_1,                                                obj_inline_c_2,                                                method_inline_c_3,                                                cargs_inline_c_4) );
 }
 
 
-jlong inline_c_Foreign_JNI_23_46357804ee4af723721f601341c61ac4eecad475(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jlong inline_c_Foreign_JNI_60_46357804ee4af723721f601341c61ac4eecad475(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallLongMethodA(env_inline_c_1,                                                obj_inline_c_2,                                                method_inline_c_3,                                                cargs_inline_c_4) );
 }
 
 
-jfloat inline_c_Foreign_JNI_24_75b26f9688a40ee63e314f73ee5f9563c48e02c0(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jfloat inline_c_Foreign_JNI_61_75b26f9688a40ee63e314f73ee5f9563c48e02c0(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallFloatMethodA(env_inline_c_1,                                                obj_inline_c_2,                                                method_inline_c_3,                                                cargs_inline_c_4) );
 }
 
 
-jdouble inline_c_Foreign_JNI_25_f33654d183f21d1a2c8ffc121684d4e60e273fa2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jdouble inline_c_Foreign_JNI_62_f33654d183f21d1a2c8ffc121684d4e60e273fa2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallDoubleMethodA(env_inline_c_1,                                                obj_inline_c_2,                                                method_inline_c_3,                                                cargs_inline_c_4) );
 }
 
 
-void inline_c_Foreign_JNI_26_5e76a5cd24826d8a13100c53ae77823083465978(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+void inline_c_Foreign_JNI_63_5e76a5cd24826d8a13100c53ae77823083465978(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
        (*env_inline_c_0)->CallStaticVoidMethodA(env_inline_c_1,                                                        cls_inline_c_2,                                                        method_inline_c_3,                                                        cargs_inline_c_4) ;
 }
 
 
-jobject inline_c_Foreign_JNI_27_6b65c20aae594d93c02434b3de002e443794ad14(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jobject inline_c_Foreign_JNI_64_6b65c20aae594d93c02434b3de002e443794ad14(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallStaticObjectMethodA(env_inline_c_1,                                                        cls_inline_c_2,                                                        method_inline_c_3,                                                        cargs_inline_c_4) );
 }
 
 
-jboolean inline_c_Foreign_JNI_28_58bcbcce6c8bf92799bd1db44c288a7b0a260a36(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jboolean inline_c_Foreign_JNI_65_58bcbcce6c8bf92799bd1db44c288a7b0a260a36(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallStaticBooleanMethodA(env_inline_c_1,                                                        cls_inline_c_2,                                                        method_inline_c_3,                                                        cargs_inline_c_4) );
 }
 
 
-jbyte inline_c_Foreign_JNI_29_1f0c41a419f29557514552df4d07022a006f2ca3(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jbyte inline_c_Foreign_JNI_66_1f0c41a419f29557514552df4d07022a006f2ca3(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallStaticByteMethodA(env_inline_c_1,                                                        cls_inline_c_2,                                                        method_inline_c_3,                                                        cargs_inline_c_4) );
 }
 
 
-jchar inline_c_Foreign_JNI_30_51a3cb1cefc6391ba5958a887d84196690a418f2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jchar inline_c_Foreign_JNI_67_51a3cb1cefc6391ba5958a887d84196690a418f2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallStaticCharMethodA(env_inline_c_1,                                                        cls_inline_c_2,                                                        method_inline_c_3,                                                        cargs_inline_c_4) );
 }
 
 
-jshort inline_c_Foreign_JNI_31_5822dfce2b301e3b90f80885a4a5838bdc57cd44(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jshort inline_c_Foreign_JNI_68_5822dfce2b301e3b90f80885a4a5838bdc57cd44(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallStaticShortMethodA(env_inline_c_1,                                                        cls_inline_c_2,                                                        method_inline_c_3,                                                        cargs_inline_c_4) );
 }
 
 
-jint inline_c_Foreign_JNI_32_4fdc28424fe7ef156763f715ef79463ed387abb2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jint inline_c_Foreign_JNI_69_4fdc28424fe7ef156763f715ef79463ed387abb2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallStaticIntMethodA(env_inline_c_1,                                                        cls_inline_c_2,                                                        method_inline_c_3,                                                        cargs_inline_c_4) );
 }
 
 
-jlong inline_c_Foreign_JNI_33_93382b358dc7f0275c6a620eaa67fdfd75167d54(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jlong inline_c_Foreign_JNI_70_93382b358dc7f0275c6a620eaa67fdfd75167d54(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallStaticLongMethodA(env_inline_c_1,                                                        cls_inline_c_2,                                                        method_inline_c_3,                                                        cargs_inline_c_4) );
 }
 
 
-jfloat inline_c_Foreign_JNI_34_89ea2435847f3d94e8b71bcceba739a077829ca9(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jfloat inline_c_Foreign_JNI_71_89ea2435847f3d94e8b71bcceba739a077829ca9(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallStaticFloatMethodA(env_inline_c_1,                                                        cls_inline_c_2,                                                        method_inline_c_3,                                                        cargs_inline_c_4) );
 }
 
 
-jdouble inline_c_Foreign_JNI_35_0b9bb41f21f19495338507ff5779f50a17ac0245(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
+jdouble inline_c_Foreign_JNI_72_0b9bb41f21f19495338507ff5779f50a17ac0245(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {
 return (       (*env_inline_c_0)->CallStaticDoubleMethodA(env_inline_c_1,                                                        cls_inline_c_2,                                                        method_inline_c_3,                                                        cargs_inline_c_4) );
 }
 
 
-jobjectArray inline_c_Foreign_JNI_36_0b57533e83360b5a6660bf703521b3b6c2fbec66(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2, jclass cls_inline_c_3) {
+jobjectArray inline_c_Foreign_JNI_73_0b57533e83360b5a6660bf703521b3b6c2fbec66(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2, jclass cls_inline_c_3) {
 return (
       (*env_inline_c_0)->NewObjectArray(env_inline_c_1,
                                         sz_inline_c_2,
@@ -259,47 +445,47 @@
 }
 
 
-jbooleanArray inline_c_Foreign_JNI_37_b1841567b8f0e99405458b9e8a3b7f3a3e20812f(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {
+jbooleanArray inline_c_Foreign_JNI_74_b1841567b8f0e99405458b9e8a3b7f3a3e20812f(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {
 return (       (*env_inline_c_0)->NewBooleanArray(env_inline_c_1,                                               sz_inline_c_2) );
 }
 
 
-jbyteArray inline_c_Foreign_JNI_38_1a9345ff427557126ba3aa5f0fb460f3df632ff8(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {
+jbyteArray inline_c_Foreign_JNI_75_1a9345ff427557126ba3aa5f0fb460f3df632ff8(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {
 return (       (*env_inline_c_0)->NewByteArray(env_inline_c_1,                                               sz_inline_c_2) );
 }
 
 
-jcharArray inline_c_Foreign_JNI_39_b00869a9422815fdc3aa43f15e3b782dc6f19e03(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {
+jcharArray inline_c_Foreign_JNI_76_b00869a9422815fdc3aa43f15e3b782dc6f19e03(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {
 return (       (*env_inline_c_0)->NewCharArray(env_inline_c_1,                                               sz_inline_c_2) );
 }
 
 
-jshortArray inline_c_Foreign_JNI_40_06a1e38de0ed2d7764757388457ed0797c72d8aa(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {
+jshortArray inline_c_Foreign_JNI_77_06a1e38de0ed2d7764757388457ed0797c72d8aa(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {
 return (       (*env_inline_c_0)->NewShortArray(env_inline_c_1,                                               sz_inline_c_2) );
 }
 
 
-jintArray inline_c_Foreign_JNI_41_af7c087746afd64be9d977ebf078c2df4b3d918e(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {
+jintArray inline_c_Foreign_JNI_78_af7c087746afd64be9d977ebf078c2df4b3d918e(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {
 return (       (*env_inline_c_0)->NewIntArray(env_inline_c_1,                                               sz_inline_c_2) );
 }
 
 
-jlongArray inline_c_Foreign_JNI_42_270c75c62cc97fdc3741af544fa35a61abf37fba(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {
+jlongArray inline_c_Foreign_JNI_79_270c75c62cc97fdc3741af544fa35a61abf37fba(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {
 return (       (*env_inline_c_0)->NewLongArray(env_inline_c_1,                                               sz_inline_c_2) );
 }
 
 
-jfloatArray inline_c_Foreign_JNI_43_312dee8af1c4b2058cb1b2703277cf297ba34224(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {
+jfloatArray inline_c_Foreign_JNI_80_312dee8af1c4b2058cb1b2703277cf297ba34224(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {
 return (       (*env_inline_c_0)->NewFloatArray(env_inline_c_1,                                               sz_inline_c_2) );
 }
 
 
-jdoubleArray inline_c_Foreign_JNI_44_103070e78986a21762e18c9aebfa9162a3565d9b(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {
+jdoubleArray inline_c_Foreign_JNI_81_103070e78986a21762e18c9aebfa9162a3565d9b(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {
 return (       (*env_inline_c_0)->NewDoubleArray(env_inline_c_1,                                               sz_inline_c_2) );
 }
 
 
-jstring inline_c_Foreign_JNI_45_d5ed5b314231e7dc3292c2329a2cb4191e262633(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jchar * ptr_inline_c_2, jsize len_inline_c_3) {
+jstring inline_c_Foreign_JNI_82_d5ed5b314231e7dc3292c2329a2cb4191e262633(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jchar * ptr_inline_c_2, jsize len_inline_c_3) {
 return (
       (*env_inline_c_0)->NewString(env_inline_c_1,
                                    ptr_inline_c_2,
@@ -307,61 +493,61 @@
 }
 
 
-jsize inline_c_Foreign_JNI_46_9be0134c89fa74c4d07a2601d81d89982ce8bdf6(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jarray array_inline_c_2) {
+jsize inline_c_Foreign_JNI_83_9be0134c89fa74c4d07a2601d81d89982ce8bdf6(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jarray array_inline_c_2) {
 return (
       (*env_inline_c_0)->GetArrayLength(env_inline_c_1,
                                         array_inline_c_2) );
 }
 
 
-jsize inline_c_Foreign_JNI_47_2e55ce4ded52c43b7b69c0c49c4425aef4f8a80b(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jstring jstr_inline_c_2) {
+jsize inline_c_Foreign_JNI_84_2e55ce4ded52c43b7b69c0c49c4425aef4f8a80b(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jstring jstr_inline_c_2) {
 return (
       (*env_inline_c_0)->GetStringLength(env_inline_c_1,
                                          jstr_inline_c_2) );
 }
 
 
-jboolean * inline_c_Foreign_JNI_48_153a97a3a91d03dbe7d10fe0e3d48afaa842ee96(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {
+jboolean * inline_c_Foreign_JNI_85_153a97a3a91d03dbe7d10fe0e3d48afaa842ee96(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {
 return (       (*env_inline_c_0)->GetBooleanArrayElements(env_inline_c_1,                                                       array_inline_c_2,                                                       NULL) );
 }
 
 
-jbyte * inline_c_Foreign_JNI_49_b630cdc25e3d575cad69a3fc3bec490a99a6ab49(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {
+jbyte * inline_c_Foreign_JNI_86_b630cdc25e3d575cad69a3fc3bec490a99a6ab49(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {
 return (       (*env_inline_c_0)->GetByteArrayElements(env_inline_c_1,                                                       array_inline_c_2,                                                       NULL) );
 }
 
 
-jchar * inline_c_Foreign_JNI_50_7c0f806fe4d40ac0c1d06b4ccccc42fdc562c8ec(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {
+jchar * inline_c_Foreign_JNI_87_7c0f806fe4d40ac0c1d06b4ccccc42fdc562c8ec(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {
 return (       (*env_inline_c_0)->GetCharArrayElements(env_inline_c_1,                                                       array_inline_c_2,                                                       NULL) );
 }
 
 
-jshort * inline_c_Foreign_JNI_51_66e42eb3b8a0e71cc0cc2b722b925689a20ed23f(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {
+jshort * inline_c_Foreign_JNI_88_66e42eb3b8a0e71cc0cc2b722b925689a20ed23f(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {
 return (       (*env_inline_c_0)->GetShortArrayElements(env_inline_c_1,                                                       array_inline_c_2,                                                       NULL) );
 }
 
 
-jint * inline_c_Foreign_JNI_52_9ca3666fbed332c3a833881ceba71295e27d5d16(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {
+jint * inline_c_Foreign_JNI_89_9ca3666fbed332c3a833881ceba71295e27d5d16(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {
 return (       (*env_inline_c_0)->GetIntArrayElements(env_inline_c_1,                                                       array_inline_c_2,                                                       NULL) );
 }
 
 
-jlong * inline_c_Foreign_JNI_53_3bd0969839fbd68b98c00a27f6197704f6e2718b(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {
+jlong * inline_c_Foreign_JNI_90_3bd0969839fbd68b98c00a27f6197704f6e2718b(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {
 return (       (*env_inline_c_0)->GetLongArrayElements(env_inline_c_1,                                                       array_inline_c_2,                                                       NULL) );
 }
 
 
-jfloat * inline_c_Foreign_JNI_54_1799b6e92e7df6d5155518d25fe2fde47055a7ff(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {
+jfloat * inline_c_Foreign_JNI_91_1799b6e92e7df6d5155518d25fe2fde47055a7ff(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {
 return (       (*env_inline_c_0)->GetFloatArrayElements(env_inline_c_1,                                                       array_inline_c_2,                                                       NULL) );
 }
 
 
-jdouble * inline_c_Foreign_JNI_55_6b454504f66bff257e7cb14d00f7064112a8f5a2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {
+jdouble * inline_c_Foreign_JNI_92_6b454504f66bff257e7cb14d00f7064112a8f5a2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {
 return (       (*env_inline_c_0)->GetDoubleArrayElements(env_inline_c_1,                                                       array_inline_c_2,                                                       NULL) );
 }
 
 
-const jchar * inline_c_Foreign_JNI_56_ac075a3bdcb535575fe36c6f7b5eb3d66ace44a7(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jstring jstr_inline_c_2) {
+const jchar * inline_c_Foreign_JNI_93_ac075a3bdcb535575fe36c6f7b5eb3d66ace44a7(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jstring jstr_inline_c_2) {
 return (
       (*env_inline_c_0)->GetStringChars(env_inline_c_1,
                                         jstr_inline_c_2,
@@ -369,87 +555,87 @@
 }
 
 
-void inline_c_Foreign_JNI_57_c405fd2cc3cc77bea5093b022f17d3b2c443e2a2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jbooleanArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jboolean * buf_inline_c_5) {
+void inline_c_Foreign_JNI_94_c405fd2cc3cc77bea5093b022f17d3b2c443e2a2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jbooleanArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jboolean * buf_inline_c_5) {
        (*env_inline_c_0)->SetBooleanArrayRegion(env_inline_c_1,                                                     array_inline_c_2,                                                     start_inline_c_3,                                                     len_inline_c_4,                                                     buf_inline_c_5) ;
 }
 
 
-void inline_c_Foreign_JNI_58_6aefb6e6ad5f3a169ff39bd2c3186b897bcd220f(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jbyteArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jbyte * buf_inline_c_5) {
+void inline_c_Foreign_JNI_95_6aefb6e6ad5f3a169ff39bd2c3186b897bcd220f(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jbyteArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jbyte * buf_inline_c_5) {
        (*env_inline_c_0)->SetByteArrayRegion(env_inline_c_1,                                                     array_inline_c_2,                                                     start_inline_c_3,                                                     len_inline_c_4,                                                     buf_inline_c_5) ;
 }
 
 
-void inline_c_Foreign_JNI_59_a1e161a18fa39331bad743b7e07b0399b3104242(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jcharArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jchar * buf_inline_c_5) {
+void inline_c_Foreign_JNI_96_a1e161a18fa39331bad743b7e07b0399b3104242(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jcharArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jchar * buf_inline_c_5) {
        (*env_inline_c_0)->SetCharArrayRegion(env_inline_c_1,                                                     array_inline_c_2,                                                     start_inline_c_3,                                                     len_inline_c_4,                                                     buf_inline_c_5) ;
 }
 
 
-void inline_c_Foreign_JNI_60_4221edb9c7b0c1666f5952fe23aad965e2f58085(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jshortArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jshort * buf_inline_c_5) {
+void inline_c_Foreign_JNI_97_4221edb9c7b0c1666f5952fe23aad965e2f58085(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jshortArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jshort * buf_inline_c_5) {
        (*env_inline_c_0)->SetShortArrayRegion(env_inline_c_1,                                                     array_inline_c_2,                                                     start_inline_c_3,                                                     len_inline_c_4,                                                     buf_inline_c_5) ;
 }
 
 
-void inline_c_Foreign_JNI_61_0cf86cc89e108bd7ed150e5aad2e7d8d8f95dd7a(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jintArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jint * buf_inline_c_5) {
+void inline_c_Foreign_JNI_98_0cf86cc89e108bd7ed150e5aad2e7d8d8f95dd7a(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jintArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jint * buf_inline_c_5) {
        (*env_inline_c_0)->SetIntArrayRegion(env_inline_c_1,                                                     array_inline_c_2,                                                     start_inline_c_3,                                                     len_inline_c_4,                                                     buf_inline_c_5) ;
 }
 
 
-void inline_c_Foreign_JNI_62_983cb43fd1962ef866086f1819815a8b05791888(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jlongArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jlong * buf_inline_c_5) {
+void inline_c_Foreign_JNI_99_983cb43fd1962ef866086f1819815a8b05791888(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jlongArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jlong * buf_inline_c_5) {
        (*env_inline_c_0)->SetLongArrayRegion(env_inline_c_1,                                                     array_inline_c_2,                                                     start_inline_c_3,                                                     len_inline_c_4,                                                     buf_inline_c_5) ;
 }
 
 
-void inline_c_Foreign_JNI_63_26c6b32031e2561eb5fc3b047d493c3a784bbf40(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jfloatArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jfloat * buf_inline_c_5) {
+void inline_c_Foreign_JNI_100_26c6b32031e2561eb5fc3b047d493c3a784bbf40(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jfloatArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jfloat * buf_inline_c_5) {
        (*env_inline_c_0)->SetFloatArrayRegion(env_inline_c_1,                                                     array_inline_c_2,                                                     start_inline_c_3,                                                     len_inline_c_4,                                                     buf_inline_c_5) ;
 }
 
 
-void inline_c_Foreign_JNI_64_fbded71aa93cca94c495be618b75c7f610619a93(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jdoubleArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jdouble * buf_inline_c_5) {
+void inline_c_Foreign_JNI_101_fbded71aa93cca94c495be618b75c7f610619a93(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jdoubleArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jdouble * buf_inline_c_5) {
        (*env_inline_c_0)->SetDoubleArrayRegion(env_inline_c_1,                                                     array_inline_c_2,                                                     start_inline_c_3,                                                     len_inline_c_4,                                                     buf_inline_c_5) ;
 }
 
 
-void inline_c_Foreign_JNI_65_5d5355f911ff38accf7df59e4f3407823efa0055(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jboolean * xs_inline_c_3) {
+void inline_c_Foreign_JNI_102_5d5355f911ff38accf7df59e4f3407823efa0055(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jboolean * xs_inline_c_3) {
        (*env_inline_c_0)->ReleaseBooleanArrayElements(env_inline_c_1,                                                           array_inline_c_2,                                                           xs_inline_c_3,                                                           JNI_ABORT) ;
 }
 
 
-void inline_c_Foreign_JNI_66_93701f28f0a45b8531f977f3ad28d48b747bb58c(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jbyte * xs_inline_c_3) {
+void inline_c_Foreign_JNI_103_93701f28f0a45b8531f977f3ad28d48b747bb58c(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jbyte * xs_inline_c_3) {
        (*env_inline_c_0)->ReleaseByteArrayElements(env_inline_c_1,                                                           array_inline_c_2,                                                           xs_inline_c_3,                                                           JNI_ABORT) ;
 }
 
 
-void inline_c_Foreign_JNI_67_d799968701da7f57e4eb07390e1efda373184222(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jchar * xs_inline_c_3) {
+void inline_c_Foreign_JNI_104_d799968701da7f57e4eb07390e1efda373184222(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jchar * xs_inline_c_3) {
        (*env_inline_c_0)->ReleaseCharArrayElements(env_inline_c_1,                                                           array_inline_c_2,                                                           xs_inline_c_3,                                                           JNI_ABORT) ;
 }
 
 
-void inline_c_Foreign_JNI_68_03e0c5a40ab324b1c42f0b70ceaeb6b1605a0ded(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jshort * xs_inline_c_3) {
+void inline_c_Foreign_JNI_105_03e0c5a40ab324b1c42f0b70ceaeb6b1605a0ded(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jshort * xs_inline_c_3) {
        (*env_inline_c_0)->ReleaseShortArrayElements(env_inline_c_1,                                                           array_inline_c_2,                                                           xs_inline_c_3,                                                           JNI_ABORT) ;
 }
 
 
-void inline_c_Foreign_JNI_69_4c2726a53e147cd6eb61733e27bfc599bc883f74(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jint * xs_inline_c_3) {
+void inline_c_Foreign_JNI_106_4c2726a53e147cd6eb61733e27bfc599bc883f74(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jint * xs_inline_c_3) {
        (*env_inline_c_0)->ReleaseIntArrayElements(env_inline_c_1,                                                           array_inline_c_2,                                                           xs_inline_c_3,                                                           JNI_ABORT) ;
 }
 
 
-void inline_c_Foreign_JNI_70_9e1790871e959852cb5032b3f2833c370b81bb0f(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jlong * xs_inline_c_3) {
+void inline_c_Foreign_JNI_107_9e1790871e959852cb5032b3f2833c370b81bb0f(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jlong * xs_inline_c_3) {
        (*env_inline_c_0)->ReleaseLongArrayElements(env_inline_c_1,                                                           array_inline_c_2,                                                           xs_inline_c_3,                                                           JNI_ABORT) ;
 }
 
 
-void inline_c_Foreign_JNI_71_44c06b418c79983d60f09ffc49851077b1feb632(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jfloat * xs_inline_c_3) {
+void inline_c_Foreign_JNI_108_44c06b418c79983d60f09ffc49851077b1feb632(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jfloat * xs_inline_c_3) {
        (*env_inline_c_0)->ReleaseFloatArrayElements(env_inline_c_1,                                                           array_inline_c_2,                                                           xs_inline_c_3,                                                           JNI_ABORT) ;
 }
 
 
-void inline_c_Foreign_JNI_72_94830601ce91790b75e74abe9c9819be2e748762(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jdouble * xs_inline_c_3) {
+void inline_c_Foreign_JNI_109_94830601ce91790b75e74abe9c9819be2e748762(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jdouble * xs_inline_c_3) {
        (*env_inline_c_0)->ReleaseDoubleArrayElements(env_inline_c_1,                                                           array_inline_c_2,                                                           xs_inline_c_3,                                                           JNI_ABORT) ;
 }
 
 
-void inline_c_Foreign_JNI_73_7a962d5f8e6114066dca42386535e4a079022eae(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jstring jstr_inline_c_2, jchar * chars_inline_c_3) {
+void inline_c_Foreign_JNI_110_7a962d5f8e6114066dca42386535e4a079022eae(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jstring jstr_inline_c_2, jchar * chars_inline_c_3) {
 
       (*env_inline_c_0)->ReleaseStringChars(env_inline_c_1,
                                             jstr_inline_c_2,
@@ -457,7 +643,7 @@
 }
 
 
-jobject inline_c_Foreign_JNI_74_bb66272284cce01d85b6ec31967e1a66eae7e0c5(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jarray array_inline_c_2, jsize i_inline_c_3) {
+jobject inline_c_Foreign_JNI_111_bb66272284cce01d85b6ec31967e1a66eae7e0c5(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jarray array_inline_c_2, jsize i_inline_c_3) {
 return (
       (*env_inline_c_0)->GetObjectArrayElement(env_inline_c_1,
                                                array_inline_c_2,
@@ -465,7 +651,7 @@
 }
 
 
-void inline_c_Foreign_JNI_75_c069b4edd080791f4858d4a7a48b8c42c99c8e4a(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobjectArray array_inline_c_2, jsize i_inline_c_3, jobject x_inline_c_4) {
+void inline_c_Foreign_JNI_112_c069b4edd080791f4858d4a7a48b8c42c99c8e4a(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobjectArray array_inline_c_2, jsize i_inline_c_3, jobject x_inline_c_4) {
 
       (*env_inline_c_0)->SetObjectArrayElement(env_inline_c_1,
                                                array_inline_c_2,
diff --git a/src/Foreign/JNI.hs b/src/Foreign/JNI.hs
--- a/src/Foreign/JNI.hs
+++ b/src/Foreign/JNI.hs
@@ -31,16 +31,59 @@
     withJVM
     -- ** Class loading
   , defineClass
+  , JNINativeMethod(..)
+  , registerNatives
+    -- ** Exceptions
+  , throw
+  , throwNew
     -- ** Query functions
   , findClass
   , getFieldID
   , getStaticFieldID
   , getMethodID
   , getStaticMethodID
+  , getObjectClass
     -- ** Field accessor functions
+    -- *** Get fields
   , getObjectField
+  , getBooleanField
+  , getIntField
+  , getLongField
+  , getCharField
+  , getShortField
+  , getByteField
+  , getDoubleField
+  , getFloatField
+    -- *** Get static fields
   , getStaticObjectField
+  , getStaticBooleanField
+  , getStaticIntField
+  , getStaticLongField
+  , getStaticCharField
+  , getStaticShortField
+  , getStaticByteField
+  , getStaticDoubleField
+  , getStaticFloatField
+    -- *** Set fields
+  , setObjectField
   , setBooleanField
+  , setIntField
+  , setLongField
+  , setCharField
+  , setShortField
+  , setByteField
+  , setDoubleField
+  , setFloatField
+    -- *** Set static fields
+  , setStaticObjectField
+  , setStaticBooleanField
+  , setStaticIntField
+  , setStaticLongField
+  , setStaticCharField
+  , setStaticShortField
+  , setStaticByteField
+  , setStaticDoubleField
+  , setStaticFloatField
     -- ** Method invocation
   , callObjectMethod
   , callBooleanMethod
@@ -108,7 +151,7 @@
   ) where
 
 import Control.Exception (Exception, bracket, finally, throwIO)
-import Control.Monad (unless)
+import Control.Monad (unless, void)
 import Data.Coerce
 import Data.Int
 import Data.IORef (IORef, newIORef, readIORef)
@@ -119,6 +162,7 @@
 import Data.Typeable (Typeable)
 import Data.TLS.PThread
 import Foreign.C (CChar)
+import Foreign.JNI.NativeMethod
 import Foreign.JNI.Types
 import qualified Foreign.JNI.String as JNI
 import Foreign.Marshal.Array
@@ -244,7 +288,35 @@
                                      $(jobject loader),
                                      $bs-ptr:buf,
                                      $bs-len:buf) } |]
+registerNatives
+  :: JClass
+  -> [JNINativeMethod]
+  -> IO ()
+registerNatives cls methods = withJNIEnv $ \env ->
+    throwIfException env $
+    withArray methods $ \cmethods -> do
+      let numMethods = fromIntegral $ length methods
+      _ <- [CU.exp| jint {
+             (*$(JNIEnv *env))->RegisterNatives($(JNIEnv *env),
+                                                $(jclass cls),
+                                                $(JNINativeMethod *cmethods),
+                                                $(int numMethods)) } |]
+      return ()
 
+throw :: Coercible o (J a) => o -> IO ()
+throw (coerce -> upcast -> obj) = withJNIEnv $ \env -> void $ do
+    [CU.exp| jint {
+       (*$(JNIEnv *env))->Throw($(JNIEnv *env),
+                                $(jobject obj)) } |]
+
+throwNew :: JClass -> JNI.String -> IO ()
+throwNew cls msg = withJNIEnv $ \env ->
+    JNI.withString msg $ \msgp -> void $ do
+    [CU.exp| jint {
+       (*$(JNIEnv *env))->ThrowNew($(JNIEnv *env),
+                                   $(jclass cls),
+                                   $(char *msgp)) } |]
+
 findClass
   :: JNI.String -- ^ Class name
   -> IO JClass
@@ -294,44 +366,86 @@
                                           $(char *fieldnamep),
                                           $(char *sigp)) } |]
 
-getObjectField
-  :: Coercible o (J a)
-  => o -- ^ Any object of any class
-  -> JFieldID
-  -> IO JObject
-getObjectField (coerce -> upcast -> obj) field = withJNIEnv $ \env ->
-    throwIfException env $
-    [CU.exp| jobject {
-      (*$(JNIEnv *env))->GetObjectField($(JNIEnv *env),
-                                        $(jobject obj),
-                                        $(jfieldID field)) } |]
-
-getStaticObjectField
-  :: JClass
-  -> JFieldID
-  -> IO JObject
-getStaticObjectField klass field = withJNIEnv $ \env ->
-    throwIfException env $
-    [CU.exp| jobject {
-      (*$(JNIEnv *env))->GetStaticObjectField($(JNIEnv *env),
-                                              $(jclass klass),
+#define GET_FIELD(name, hs_rettype, c_rettype) \
+get/**/name/**/Field :: Coercible o (J a) => o -> JFieldID -> IO hs_rettype; \
+get/**/name/**/Field (coerce -> upcast -> obj) field = withJNIEnv $ \env -> \
+    throwIfException env $ \
+    [CU.exp| c_rettype { \
+      (*$(JNIEnv *env))->Get/**/name/**/Field($(JNIEnv *env), \
+                                              $(jobject obj), \
                                               $(jfieldID field)) } |]
 
-setBooleanField
-  :: Coercible o (J a)
-  => o -- ^ Any object of any class
-  -> JFieldID
-  -> Bool
-  -> IO ()
-setBooleanField (coerce -> upcast -> obj) field (fromEnum -> fromIntegral -> b) =
-    withJNIEnv $ \env ->
-    throwIfException env $
-    [CU.block| void {
-      (*$(JNIEnv *env))->SetBooleanField($(JNIEnv *env),
-                                        $(jobject obj),
-                                        $(jfieldID field),
-                                        $(jboolean b)); } |]
+GET_FIELD(Object, JObject, jobject)
+GET_FIELD(Boolean, Word8, jboolean)
+GET_FIELD(Byte, CChar, jbyte)
+GET_FIELD(Char, Word16, jchar)
+GET_FIELD(Short, Int16, jshort)
+GET_FIELD(Int, Int32, jint)
+GET_FIELD(Long, Int64, jlong)
+GET_FIELD(Float, Float, jfloat)
+GET_FIELD(Double, Double, jdouble)
 
+#define GET_STATIC_FIELD(name, hs_rettype, c_rettype) \
+getStatic/**/name/**/Field :: JClass -> JFieldID -> IO hs_rettype; \
+getStatic/**/name/**/Field klass field = withJNIEnv $ \env -> \
+    throwIfException env $ \
+    [CU.exp| c_rettype { \
+      (*$(JNIEnv *env))->GetStatic/**/name/**/Field($(JNIEnv *env), \
+                                                    $(jclass klass), \
+                                                    $(jfieldID field)) } |]
+
+GET_STATIC_FIELD(Object, JObject, jobject)
+GET_STATIC_FIELD(Boolean, Word8, jboolean)
+GET_STATIC_FIELD(Byte, CChar, jbyte)
+GET_STATIC_FIELD(Char, Word16, jchar)
+GET_STATIC_FIELD(Short, Int16, jshort)
+GET_STATIC_FIELD(Int, Int32, jint)
+GET_STATIC_FIELD(Long, Int64, jlong)
+GET_STATIC_FIELD(Float, Float, jfloat)
+GET_STATIC_FIELD(Double, Double, jdouble)
+
+#define SET_FIELD(name, hs_fieldtype, c_fieldtype) \
+set/**/name/**/Field :: Coercible o (J a) => o -> JFieldID -> hs_fieldtype -> IO (); \
+set/**/name/**/Field (coerce -> upcast -> obj) field x = \
+    withJNIEnv $ \env -> \
+    throwIfException env $ \
+    [CU.block| void { \
+      (*$(JNIEnv *env))->Set/**/name/**/Field($(JNIEnv *env), \
+                                              $(jobject obj), \
+                                              $(jfieldID field), \
+                                              $(c_fieldtype x)); } |]
+
+SET_FIELD(Object, JObject, jobject)
+SET_FIELD(Boolean, Word8, jboolean)
+SET_FIELD(Byte, CChar, jbyte)
+SET_FIELD(Char, Word16, jchar)
+SET_FIELD(Short, Int16, jshort)
+SET_FIELD(Int, Int32, jint)
+SET_FIELD(Long, Int64, jlong)
+SET_FIELD(Float, Float, jfloat)
+SET_FIELD(Double, Double, jdouble)
+
+#define SET_STATIC_FIELD(name, hs_fieldtype, c_fieldtype) \
+setStatic/**/name/**/Field :: JClass -> JFieldID -> hs_fieldtype -> IO (); \
+setStatic/**/name/**/Field klass field x = \
+    withJNIEnv $ \env -> \
+    throwIfException env $ \
+    [CU.block| void { \
+      (*$(JNIEnv *env))->SetStatic/**/name/**/Field($(JNIEnv *env), \
+                                                    $(jclass klass), \
+                                                    $(jfieldID field), \
+                                                    $(c_fieldtype x)); } |]
+
+SET_STATIC_FIELD(Object, JObject, jobject)
+SET_STATIC_FIELD(Boolean, Word8, jboolean)
+SET_STATIC_FIELD(Byte, CChar, jbyte)
+SET_STATIC_FIELD(Char, Word16, jchar)
+SET_STATIC_FIELD(Short, Int16, jshort)
+SET_STATIC_FIELD(Int, Int32, jint)
+SET_STATIC_FIELD(Long, Int64, jlong)
+SET_STATIC_FIELD(Float, Float, jfloat)
+SET_STATIC_FIELD(Double, Double, jdouble)
+
 getMethodID
   :: JClass -- ^ A class object as returned by 'findClass'
   -> JNI.String -- ^ Field name
@@ -361,6 +475,12 @@
                                            $(jclass cls),
                                            $(char *methodnamep),
                                            $(char *sigp)) } |]
+
+getObjectClass :: Coercible o (J ty) => o -> IO JClass
+getObjectClass (coerce -> upcast -> obj) = withJNIEnv $ \env ->
+    [CU.exp| jclass {
+      (*$(JNIEnv *env))->GetObjectClass($(JNIEnv *env),
+                                        $(jobject obj)) } |]
 
 -- Modern CPP does have ## for concatenating strings, but we use the hacky /**/
 -- comment syntax for string concatenation. This is because GHC passes
diff --git a/src/Foreign/JNI/NativeMethod.hsc b/src/Foreign/JNI/NativeMethod.hsc
new file mode 100644
--- /dev/null
+++ b/src/Foreign/JNI/NativeMethod.hsc
@@ -0,0 +1,40 @@
+-- | Bindings to the JNINativeMethod struct.
+
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE RecordWildCards #-}
+
+module Foreign.JNI.NativeMethod where
+
+import qualified Data.ByteString.Unsafe as BS
+import qualified Foreign.JNI.String as JNI
+import Foreign.Ptr (FunPtr)
+import Foreign.Storable (Storable(..))
+
+#include <jni.h>
+
+#if __GLASGOW_HASKELL__ < 800
+#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)
+#endif
+
+data JNINativeMethod = forall a. JNINativeMethod
+  { jniNativeMethodName :: JNI.String
+  , jniNativeMethodSignature :: JNI.String
+  , jniNativeMethodFunPtr :: FunPtr a
+  }
+
+instance Storable JNINativeMethod where
+  sizeOf _ = #{size JNINativeMethod}
+  alignment _ = #{alignment JNINativeMethod}
+  peek ptr = do
+      name <- BS.unsafePackCString =<< #{peek JNINativeMethod, name} ptr
+      sig <- BS.unsafePackCString =<< #{peek JNINativeMethod, signature} ptr
+      fptr <- #{peek JNINativeMethod, fnPtr} ptr
+      return $
+        JNINativeMethod
+          (JNI.unsafeFromByteString name)
+          (JNI.unsafeFromByteString sig)
+          fptr
+  poke ptr JNINativeMethod{..} = do
+      JNI.withString jniNativeMethodName $ #{poke JNINativeMethod, name} ptr
+      JNI.withString jniNativeMethodSignature $ #{poke JNINativeMethod, signature} ptr
+      #{poke JNINativeMethod, fnPtr} ptr jniNativeMethodFunPtr
diff --git a/src/Foreign/JNI/Types.hs b/src/Foreign/JNI/Types.hs
--- a/src/Foreign/JNI/Types.hs
+++ b/src/Foreign/JNI/Types.hs
@@ -77,6 +77,7 @@
 import Data.String (fromString)
 import Data.Word
 import Foreign.C (CChar)
+import Foreign.JNI.NativeMethod
 import qualified Foreign.JNI.String as JNI
 import Foreign.Ptr
 import Foreign.Storable (Storable(..))
@@ -346,6 +347,7 @@
       -- Internal types
       , (TypeName "JavaVM", [t| JVM |])
       , (TypeName "JNIEnv", [t| JNIEnv |])
+      , (TypeName "JNINativeMethod", [t| JNINativeMethod |])
       , (TypeName "jfieldID", [t| JFieldID |])
       , (TypeName "jmethodID", [t| JMethodID |])
       , (TypeName "jsize", [t| Int32 |])
