Implement more of the exception/object/class JNI functions.

Change-Id: Id835c1a37e5034d11e2fc43ccf49e578510abfc1
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 243a29d..9aa23bb 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -582,28 +582,68 @@
     return AddLocalReference<jobject>(ts, field);
   }
 
+  static jclass GetObjectClass(JNIEnv* env, jobject java_object) {
+    ScopedJniThreadState ts(env);
+    Object* o = Decode<Object*>(ts, java_object);
+    return AddLocalReference<jclass>(ts, o->GetClass());
+  }
+
   static jclass GetSuperclass(JNIEnv* env, jclass java_class) {
     ScopedJniThreadState ts(env);
     Class* c = Decode<Class*>(ts, java_class);
     return AddLocalReference<jclass>(ts, c->GetSuperClass());
   }
 
-  static jboolean IsAssignableFrom(JNIEnv* env, jclass sub, jclass sup) {
+  static jboolean IsAssignableFrom(JNIEnv* env, jclass java_class1, jclass java_class2) {
     ScopedJniThreadState ts(env);
-    UNIMPLEMENTED(FATAL);
-    return JNI_FALSE;
+    Class* c1 = Decode<Class*>(ts, java_class1);
+    Class* c2 = Decode<Class*>(ts, java_class2);
+    return c1->IsAssignableFrom(c2) ? JNI_TRUE : JNI_FALSE;
   }
 
-  static jint Throw(JNIEnv* env, jthrowable obj) {
+  static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass clazz) {
     ScopedJniThreadState ts(env);
-    UNIMPLEMENTED(FATAL);
-    return 0;
+    CHECK_NE(static_cast<jclass>(NULL), clazz);
+    if (jobj == NULL) {
+      // NB. JNI is different from regular Java instanceof in this respect
+      return JNI_TRUE;
+    } else {
+      Object* obj = Decode<Object*>(ts, jobj);
+      Class* klass = Decode<Class*>(ts, clazz);
+      return Object::InstanceOf(obj, klass) ? JNI_TRUE : JNI_FALSE;
+    }
   }
 
-  static jint ThrowNew(JNIEnv* env, jclass clazz, const char* msg) {
+  static jint Throw(JNIEnv* env, jthrowable java_exception) {
+    ScopedJniThreadState ts(env);
+    Object* exception = Decode<Object*>(ts, java_exception);
+    if (exception == NULL) {
+      return JNI_ERR;
+    }
+    ts.Self()->SetException(exception);
+    return JNI_OK;
+  }
+
+  static jint ThrowNew(JNIEnv* env, jclass java_class, const char* msg) {
+    ScopedJniThreadState ts(env);
+    Class* c = Decode<Class*>(ts, java_class);
+    ts.Self()->ThrowNewException(c, msg);
+    return JNI_OK;
+  }
+
+  static jboolean ExceptionCheck(JNIEnv* env) {
+    ScopedJniThreadState ts(env);
+    return ts.Self()->IsExceptionPending() ? JNI_TRUE : JNI_FALSE;
+  }
+
+  static void ExceptionClear(JNIEnv* env) {
+    ScopedJniThreadState ts(env);
+    ts.Self()->ClearException();
+  }
+
+  static void ExceptionDescribe(JNIEnv* env) {
     ScopedJniThreadState ts(env);
     UNIMPLEMENTED(FATAL);
-    return 0;
   }
 
   static jthrowable ExceptionOccurred(JNIEnv* env) {
@@ -627,16 +667,6 @@
     }
   }
 
-  static void ExceptionDescribe(JNIEnv* env) {
-    ScopedJniThreadState ts(env);
-    UNIMPLEMENTED(FATAL);
-  }
-
-  static void ExceptionClear(JNIEnv* env) {
-    ScopedJniThreadState ts(env);
-    ts.Self()->ClearException();
-  }
-
   static void FatalError(JNIEnv* env, const char* msg) {
     ScopedJniThreadState ts(env);
     LOG(FATAL) << "JNI FatalError called: " << msg;
@@ -791,25 +821,6 @@
     return local_result;
   }
 
-  static jclass GetObjectClass(JNIEnv* env, jobject obj) {
-    ScopedJniThreadState ts(env);
-    UNIMPLEMENTED(FATAL);
-    return NULL;
-  }
-
-  static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass clazz) {
-    ScopedJniThreadState ts(env);
-    CHECK_NE(static_cast<jclass>(NULL), clazz);
-    if (jobj == NULL) {
-      // NB. JNI is different from regular Java instanceof in this respect
-      return JNI_TRUE;
-    } else {
-      Object* obj = Decode<Object*>(ts, jobj);
-      Class* klass = Decode<Class*>(ts, clazz);
-      return Object::InstanceOf(obj, klass) ? JNI_TRUE : JNI_FALSE;
-    }
-  }
-
   static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
     ScopedJniThreadState ts(env);
     return FindMethodID(ts, c, name, sig, false);
@@ -2066,11 +2077,6 @@
     UNIMPLEMENTED(FATAL);
   }
 
-  static jboolean ExceptionCheck(JNIEnv* env) {
-    ScopedJniThreadState ts(env);
-    return ts.Self()->IsExceptionPending() ? JNI_TRUE : JNI_FALSE;
-  }
-
   static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
     ScopedJniThreadState ts(env);
     UNIMPLEMENTED(FATAL);