Merge "Declare variable for all art dex tests."
diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc
index d3477c9..435242a 100644
--- a/compiler/dex/quick/arm/call_arm.cc
+++ b/compiler/dex/quick/arm/call_arm.cc
@@ -268,6 +268,7 @@
     MarkPossibleNullPointerException(opt_flags);
     LoadConstantNoClobber(rs_r3, 0);
     LIR* slow_unlock_branch = OpCmpBranch(kCondNe, rs_r1, rs_r2, NULL);
+    GenMemBarrier(kStoreLoad);
     Store32Disp(rs_r0, mirror::Object::MonitorOffset().Int32Value(), rs_r3);
     LIR* unlock_success_branch = OpUnconditionalBranch(NULL);
 
@@ -285,7 +286,6 @@
 
     LIR* success_target = NewLIR0(kPseudoTargetLabel);
     unlock_success_branch->target = success_target;
-    GenMemBarrier(kStoreLoad);
   } else {
     // Explicit null-check as slow-path is entered using an IT.
     GenNullCheck(rs_r0, opt_flags);
@@ -295,7 +295,8 @@
     LoadConstantNoClobber(rs_r3, 0);
     // Is lock unheld on lock or held by us (==thread_id) on unlock?
     OpRegReg(kOpCmp, rs_r1, rs_r2);
-    LIR* it = OpIT(kCondEq, "EE");
+    LIR* it = OpIT(kCondEq, "TEE");
+    GenMemBarrier(kStoreLoad);
     Store32Disp/*eq*/(rs_r0, mirror::Object::MonitorOffset().Int32Value(), rs_r3);
     // Go expensive route - UnlockObjectFromCode(obj);
     LoadWordDisp/*ne*/(rs_rARM_SELF, QUICK_ENTRYPOINT_OFFSET(4, pUnlockObject).Int32Value(),
@@ -304,7 +305,6 @@
     LIR* call_inst = OpReg(kOpBlx/*ne*/, rs_rARM_LR);
     OpEndIT(it);
     MarkSafepointPC(call_inst);
-    GenMemBarrier(kStoreLoad);
   }
 }
 
diff --git a/compiler/elf_writer_mclinker.cc b/compiler/elf_writer_mclinker.cc
index eb9b230..aa4a5b2 100644
--- a/compiler/elf_writer_mclinker.cc
+++ b/compiler/elf_writer_mclinker.cc
@@ -361,8 +361,9 @@
       ClassLinker* linker = Runtime::Current()->GetClassLinker();
       // Unchecked as we hold mutator_lock_ on entry.
       ScopedObjectAccessUnchecked soa(Thread::Current());
-      Handle<mirror::DexCache> dex_cache(soa.Self(), linker->FindDexCache(dex_file));
-      Handle<mirror::ClassLoader> class_loader(soa.Self(), nullptr);
+      StackHandleScope<2> hs(soa.Self());
+      Handle<mirror::DexCache> dex_cache(hs.NewHandle(linker->FindDexCache(dex_file)));
+      auto class_loader(hs.NewHandle<mirror::ClassLoader>(nullptr));
       method = linker->ResolveMethod(dex_file, method_idx, dex_cache, class_loader, NULL, invoke_type);
       CHECK(method != NULL);
     }
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 7d7024a..ad796f8 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -958,9 +958,7 @@
   bool image = (!image_filename.empty());
   if (!image && boot_image_filename.empty()) {
     boot_image_filename += GetAndroidRoot();
-    boot_image_filename += "/framework/boot-";
-    boot_image_filename += GetInstructionSetString(instruction_set);
-    boot_image_filename += ".art";
+    boot_image_filename += "/framework/boot.art";
   }
   std::string boot_image_option;
   if (!boot_image_filename.empty()) {
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 4886561..5212576 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -399,7 +399,7 @@
     @ unlocked case - r2 holds thread id with count of 0
     strex  r3, r2, [r0, #LOCK_WORD_OFFSET]
     cbnz   r3, .Lstrex_fail           @ store failed, retry
-    dmb    ish                        @ full (LoadLoad) memory barrier
+    dmb    ish                        @ full (LoadLoad|LoadStore) memory barrier
     bx lr
 .Lstrex_fail:
     b .Lretry_lock                    @ unlikely forward branch, need to reload and recheck r1/r2
@@ -442,7 +442,7 @@
     cmp    r1, #65536
     bpl    .Lrecursive_thin_unlock
     @ transition to unlocked, r3 holds 0
-    dmb    ish                        @ full (StoreLoad) memory barrier
+    dmb    ish                        @ full (LoadStore|StoreStore) memory barrier
     str    r3, [r0, #LOCK_WORD_OFFSET]
     bx     lr
 .Lrecursive_thin_unlock:
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index 2a21144..f2050b3 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -1014,7 +1014,7 @@
     cbnz   w1, .Lnot_unlocked         // already thin locked
     stxr   w3, w2, [x4]
     cbnz   w3, .Lstrex_fail           // store failed, retry
-    dmb    ishld                      // full (LoadLoad) memory barrier, TODO: acquire-release
+    dmb    ishld                      // full (LoadLoad|LoadStore) memory barrier
     ret
 .Lstrex_fail:
     b .Lretry_lock                    // unlikely forward branch, need to reload and recheck r1/r2
@@ -1058,7 +1058,7 @@
     cmp    w1, #65536
     bpl    .Lrecursive_thin_unlock
     // transition to unlocked, w3 holds 0
-    dmb    ish                        // full (StoreLoad) memory barrier
+    dmb    ish                        // full (LoadStore|StoreStore) memory barrier
     str    w3, [x0, #LOCK_WORD_OFFSET]
     ret
 .Lrecursive_thin_unlock:
@@ -1444,7 +1444,7 @@
  * | RDI/Method*       |  <- X0
  * #-------------------#
  * | local ref cookie  | // 4B
- * |   handle scope size       | // 4B
+ * | handle scope size | // 4B
  * #-------------------#
  * | JNI Call Stack    |
  * #-------------------#    <--- SP on native call
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index 73214ea..9c86c75 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -1050,12 +1050,12 @@
  * | Return            |
  * | Callee-Save Data  |
  * #-------------------#
- * | handle scope              |
+ * | handle scope      |
  * #-------------------#
  * | Method*           |    <--- (1)
  * #-------------------#
  * | local ref cookie  | // 4B
- * | handle scope size         | // 4B   TODO: roll into call stack alignment?
+ * | handle scope size | // 4B   TODO: roll into call stack alignment?
  * #-------------------#
  * | JNI Call Stack    |
  * #-------------------#    <--- SP on native call
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc
index 0d5a805..cfd0c00 100644
--- a/runtime/check_jni.cc
+++ b/runtime/check_jni.cc
@@ -179,7 +179,7 @@
   // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
   // circumstances, but this is incorrect.
   void CheckClassName(const char* class_name) {
-    if (!IsValidJniClassName(class_name)) {
+    if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
       JniAbortF(function_name_,
                 "illegal class name '%s'\n"
                 "    (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 3d268e4..9034560 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2215,7 +2215,10 @@
     DCHECK(self->IsExceptionPending());
     return nullptr;
   }
-
+  if (UNLIKELY(component_type->IsPrimitiveVoid())) {
+    ThrowNoClassDefFoundError("Attempt to create array of void primitive type");
+    return nullptr;
+  }
   // See if the component type is already loaded.  Array classes are
   // always associated with the class loader of their underlying
   // element type -- an array of Strings goes with the loader for
diff --git a/runtime/handle_scope-inl.h b/runtime/handle_scope-inl.h
index b9b51fd..634f2be 100644
--- a/runtime/handle_scope-inl.h
+++ b/runtime/handle_scope-inl.h
@@ -25,7 +25,7 @@
 namespace art {
 
 template<size_t kNumReferences>
-StackHandleScope<kNumReferences>::StackHandleScope(Thread* self)
+inline StackHandleScope<kNumReferences>::StackHandleScope(Thread* self)
     : HandleScope(kNumReferences), self_(self), pos_(0) {
   // TODO: Figure out how to use a compile assert.
   DCHECK_EQ(OFFSETOF_MEMBER(HandleScope, references_),
@@ -37,7 +37,7 @@
 }
 
 template<size_t kNumReferences>
-StackHandleScope<kNumReferences>::~StackHandleScope() {
+inline StackHandleScope<kNumReferences>::~StackHandleScope() {
   HandleScope* top_handle_scope = self_->PopHandleScope();
   DCHECK_EQ(top_handle_scope, this);
 }
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 4634971..21dab8d 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -518,16 +518,28 @@
   SafeMap<std::string, SharedLibrary*> libraries_;
 };
 
-#define CHECK_NON_NULL_ARGUMENT(value) CHECK_NON_NULL_ARGUMENT_FN_NAME(__FUNCTION__, value)
+#define CHECK_NON_NULL_ARGUMENT(value) \
+    CHECK_NON_NULL_ARGUMENT_FN_NAME(__FUNCTION__, value, nullptr)
 
-#define CHECK_NON_NULL_ARGUMENT_FN_NAME(name, value) \
+#define CHECK_NON_NULL_ARGUMENT_RETURN_VOID(value) \
+    CHECK_NON_NULL_ARGUMENT_FN_NAME(__FUNCTION__, value, )
+
+#define CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(value) \
+    CHECK_NON_NULL_ARGUMENT_FN_NAME(__FUNCTION__, value, 0)
+
+#define CHECK_NON_NULL_ARGUMENT_RETURN(value, return_val) \
+    CHECK_NON_NULL_ARGUMENT_FN_NAME(__FUNCTION__, value, return_val)
+
+#define CHECK_NON_NULL_ARGUMENT_FN_NAME(name, value, return_val) \
   if (UNLIKELY(value == nullptr)) { \
     JniAbortF(name, #value " == null"); \
+    return return_val; \
   }
 
 #define CHECK_NON_NULL_MEMCPY_ARGUMENT(length, value) \
   if (UNLIKELY(length != 0 && value == nullptr)) { \
     JniAbortF(__FUNCTION__, #value " == null"); \
+    return; \
   }
 
 class JNI {
@@ -614,8 +626,8 @@
   }
 
   static jboolean IsAssignableFrom(JNIEnv* env, jclass java_class1, jclass java_class2) {
-    CHECK_NON_NULL_ARGUMENT(java_class1);
-    CHECK_NON_NULL_ARGUMENT(java_class2);
+    CHECK_NON_NULL_ARGUMENT_RETURN(java_class1, JNI_FALSE);
+    CHECK_NON_NULL_ARGUMENT_RETURN(java_class2, JNI_FALSE);
     ScopedObjectAccess soa(env);
     mirror::Class* c1 = soa.Decode<mirror::Class*>(java_class1);
     mirror::Class* c2 = soa.Decode<mirror::Class*>(java_class2);
@@ -623,7 +635,7 @@
   }
 
   static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass java_class) {
-    CHECK_NON_NULL_ARGUMENT(java_class);
+    CHECK_NON_NULL_ARGUMENT_RETURN(java_class, JNI_FALSE);
     if (jobj == nullptr) {
       // Note: JNI is different from regular Java instanceof in this respect
       return JNI_TRUE;
@@ -647,7 +659,7 @@
   }
 
   static jint ThrowNew(JNIEnv* env, jclass c, const char* msg) {
-    CHECK_NON_NULL_ARGUMENT(c);
+    CHECK_NON_NULL_ARGUMENT_RETURN(c, JNI_ERR);
     return ThrowNewException(env, c, msg, nullptr);
   }
 
@@ -914,8 +926,8 @@
   static jboolean CallBooleanMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -923,15 +935,15 @@
   }
 
   static jboolean CallBooleanMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetZ();
   }
 
   static jboolean CallBooleanMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
                                                args).GetZ();
@@ -940,8 +952,8 @@
   static jbyte CallByteMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -949,15 +961,15 @@
   }
 
   static jbyte CallByteMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetB();
   }
 
   static jbyte CallByteMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
                                                args).GetB();
@@ -966,8 +978,8 @@
   static jchar CallCharMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -975,15 +987,15 @@
   }
 
   static jchar CallCharMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetC();
   }
 
   static jchar CallCharMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
                                                args).GetC();
@@ -992,8 +1004,8 @@
   static jdouble CallDoubleMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1001,15 +1013,15 @@
   }
 
   static jdouble CallDoubleMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetD();
   }
 
   static jdouble CallDoubleMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
                                                args).GetD();
@@ -1018,8 +1030,8 @@
   static jfloat CallFloatMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1027,15 +1039,15 @@
   }
 
   static jfloat CallFloatMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetF();
   }
 
   static jfloat CallFloatMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
                                                args).GetF();
@@ -1044,8 +1056,8 @@
   static jint CallIntMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1053,15 +1065,15 @@
   }
 
   static jint CallIntMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetI();
   }
 
   static jint CallIntMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
                                                args).GetI();
@@ -1070,8 +1082,8 @@
   static jlong CallLongMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1079,15 +1091,15 @@
   }
 
   static jlong CallLongMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetJ();
   }
 
   static jlong CallLongMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
                                                args).GetJ();
@@ -1096,8 +1108,8 @@
   static jshort CallShortMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1105,15 +1117,15 @@
   }
 
   static jshort CallShortMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetS();
   }
 
   static jshort CallShortMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
                                                args).GetS();
@@ -1122,23 +1134,23 @@
   static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
     ScopedObjectAccess soa(env);
     InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap);
     va_end(ap);
   }
 
   static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
     ScopedObjectAccess soa(env);
     InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args);
   }
 
   static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
     ScopedObjectAccess soa(env);
     InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args);
   }
@@ -1177,8 +1189,8 @@
                                               ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1187,16 +1199,16 @@
 
   static jboolean CallNonvirtualBooleanMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                                va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetZ();
   }
 
   static jboolean CallNonvirtualBooleanMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                                jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetZ();
   }
@@ -1204,8 +1216,8 @@
   static jbyte CallNonvirtualByteMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1214,16 +1226,16 @@
 
   static jbyte CallNonvirtualByteMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                          va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetB();
   }
 
   static jbyte CallNonvirtualByteMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                          jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetB();
   }
@@ -1231,8 +1243,8 @@
   static jchar CallNonvirtualCharMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1241,16 +1253,16 @@
 
   static jchar CallNonvirtualCharMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                          va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetC();
   }
 
   static jchar CallNonvirtualCharMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                          jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetC();
   }
@@ -1258,8 +1270,8 @@
   static jshort CallNonvirtualShortMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1268,16 +1280,16 @@
 
   static jshort CallNonvirtualShortMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                            va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetS();
   }
 
   static jshort CallNonvirtualShortMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                            jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetS();
   }
@@ -1285,8 +1297,8 @@
   static jint CallNonvirtualIntMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1295,16 +1307,16 @@
 
   static jint CallNonvirtualIntMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                        va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetI();
   }
 
   static jint CallNonvirtualIntMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                        jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetI();
   }
@@ -1312,8 +1324,8 @@
   static jlong CallNonvirtualLongMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1322,16 +1334,16 @@
 
   static jlong CallNonvirtualLongMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                          va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetJ();
   }
 
   static jlong CallNonvirtualLongMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                          jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetJ();
   }
@@ -1339,8 +1351,8 @@
   static jfloat CallNonvirtualFloatMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1349,16 +1361,16 @@
 
   static jfloat CallNonvirtualFloatMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                            va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetF();
   }
 
   static jfloat CallNonvirtualFloatMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                            jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetF();
   }
@@ -1366,8 +1378,8 @@
   static jdouble CallNonvirtualDoubleMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1376,16 +1388,16 @@
 
   static jdouble CallNonvirtualDoubleMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                              va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetD();
   }
 
   static jdouble CallNonvirtualDoubleMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                              jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetD();
   }
@@ -1393,8 +1405,8 @@
   static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
     ScopedObjectAccess soa(env);
     InvokeWithVarArgs(soa, obj, mid, ap);
     va_end(ap);
@@ -1402,16 +1414,16 @@
 
   static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                         va_list args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
     ScopedObjectAccess soa(env);
     InvokeWithVarArgs(soa, obj, mid, args);
   }
 
   static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                         jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(obj);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
     ScopedObjectAccess soa(env);
     InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args);
   }
@@ -1450,8 +1462,8 @@
   }
 
   static void SetObjectField(JNIEnv* env, jobject java_object, jfieldID fid, jobject java_value) {
-    CHECK_NON_NULL_ARGUMENT(java_object);
-    CHECK_NON_NULL_ARGUMENT(fid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_object);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid);
     ScopedObjectAccess soa(env);
     mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
     mirror::Object* v = soa.Decode<mirror::Object*>(java_value);
@@ -1460,7 +1472,7 @@
   }
 
   static void SetStaticObjectField(JNIEnv* env, jclass, jfieldID fid, jobject java_value) {
-    CHECK_NON_NULL_ARGUMENT(fid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid);
     ScopedObjectAccess soa(env);
     mirror::Object* v = soa.Decode<mirror::Object*>(java_value);
     mirror::ArtField* f = soa.DecodeField(fid);
@@ -1468,29 +1480,29 @@
   }
 
 #define GET_PRIMITIVE_FIELD(fn, instance) \
-  CHECK_NON_NULL_ARGUMENT(instance); \
-  CHECK_NON_NULL_ARGUMENT(fid); \
+  CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(instance); \
+  CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \
   ScopedObjectAccess soa(env); \
   mirror::Object* o = soa.Decode<mirror::Object*>(instance); \
   mirror::ArtField* f = soa.DecodeField(fid); \
   return f->Get ##fn (o)
 
 #define GET_STATIC_PRIMITIVE_FIELD(fn) \
-  CHECK_NON_NULL_ARGUMENT(fid); \
+  CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \
   ScopedObjectAccess soa(env); \
   mirror::ArtField* f = soa.DecodeField(fid); \
   return f->Get ##fn (f->GetDeclaringClass())
 
 #define SET_PRIMITIVE_FIELD(fn, instance, value) \
-  CHECK_NON_NULL_ARGUMENT(instance); \
-  CHECK_NON_NULL_ARGUMENT(fid); \
+  CHECK_NON_NULL_ARGUMENT_RETURN_VOID(instance); \
+  CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \
   ScopedObjectAccess soa(env); \
   mirror::Object* o = soa.Decode<mirror::Object*>(instance); \
   mirror::ArtField* f = soa.DecodeField(fid); \
   f->Set ##fn <false>(o, value)
 
 #define SET_STATIC_PRIMITIVE_FIELD(fn, value) \
-  CHECK_NON_NULL_ARGUMENT(fid); \
+  CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \
   ScopedObjectAccess soa(env); \
   mirror::ArtField* f = soa.DecodeField(fid); \
   f->Set ##fn <false>(f->GetDeclaringClass(), value)
@@ -1651,7 +1663,7 @@
   static jboolean CallStaticBooleanMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
     va_end(ap);
@@ -1659,13 +1671,13 @@
   }
 
   static jboolean CallStaticBooleanMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, nullptr, mid, args).GetZ();
   }
 
   static jboolean CallStaticBooleanMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, nullptr, mid, args).GetZ();
   }
@@ -1673,7 +1685,7 @@
   static jbyte CallStaticByteMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
     va_end(ap);
@@ -1681,13 +1693,13 @@
   }
 
   static jbyte CallStaticByteMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, nullptr, mid, args).GetB();
   }
 
   static jbyte CallStaticByteMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, nullptr, mid, args).GetB();
   }
@@ -1695,7 +1707,7 @@
   static jchar CallStaticCharMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
     va_end(ap);
@@ -1703,13 +1715,13 @@
   }
 
   static jchar CallStaticCharMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, nullptr, mid, args).GetC();
   }
 
   static jchar CallStaticCharMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, nullptr, mid, args).GetC();
   }
@@ -1717,7 +1729,7 @@
   static jshort CallStaticShortMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
     va_end(ap);
@@ -1725,13 +1737,13 @@
   }
 
   static jshort CallStaticShortMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, nullptr, mid, args).GetS();
   }
 
   static jshort CallStaticShortMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, nullptr, mid, args).GetS();
   }
@@ -1739,7 +1751,7 @@
   static jint CallStaticIntMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
     va_end(ap);
@@ -1747,13 +1759,13 @@
   }
 
   static jint CallStaticIntMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, nullptr, mid, args).GetI();
   }
 
   static jint CallStaticIntMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, nullptr, mid, args).GetI();
   }
@@ -1761,7 +1773,7 @@
   static jlong CallStaticLongMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
     va_end(ap);
@@ -1769,13 +1781,13 @@
   }
 
   static jlong CallStaticLongMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, nullptr, mid, args).GetJ();
   }
 
   static jlong CallStaticLongMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, nullptr, mid, args).GetJ();
   }
@@ -1783,7 +1795,7 @@
   static jfloat CallStaticFloatMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
     va_end(ap);
@@ -1791,13 +1803,13 @@
   }
 
   static jfloat CallStaticFloatMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, nullptr, mid, args).GetF();
   }
 
   static jfloat CallStaticFloatMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, nullptr, mid, args).GetF();
   }
@@ -1805,7 +1817,7 @@
   static jdouble CallStaticDoubleMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
     va_end(ap);
@@ -1813,13 +1825,13 @@
   }
 
   static jdouble CallStaticDoubleMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, nullptr, mid, args).GetD();
   }
 
   static jdouble CallStaticDoubleMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, nullptr, mid, args).GetD();
   }
@@ -1827,20 +1839,20 @@
   static void CallStaticVoidMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
     ScopedObjectAccess soa(env);
     InvokeWithVarArgs(soa, nullptr, mid, ap);
     va_end(ap);
   }
 
   static void CallStaticVoidMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
     ScopedObjectAccess soa(env);
     InvokeWithVarArgs(soa, nullptr, mid, args);
   }
 
   static void CallStaticVoidMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(mid);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
     ScopedObjectAccess soa(env);
     InvokeWithJValues(soa, nullptr, mid, args);
   }
@@ -1869,20 +1881,20 @@
   }
 
   static jsize GetStringLength(JNIEnv* env, jstring java_string) {
-    CHECK_NON_NULL_ARGUMENT(java_string);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(java_string);
     ScopedObjectAccess soa(env);
     return soa.Decode<mirror::String*>(java_string)->GetLength();
   }
 
   static jsize GetStringUTFLength(JNIEnv* env, jstring java_string) {
-    CHECK_NON_NULL_ARGUMENT(java_string);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(java_string);
     ScopedObjectAccess soa(env);
     return soa.Decode<mirror::String*>(java_string)->GetUtfLength();
   }
 
   static void GetStringRegion(JNIEnv* env, jstring java_string, jsize start, jsize length,
                               jchar* buf) {
-    CHECK_NON_NULL_ARGUMENT(java_string);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_string);
     ScopedObjectAccess soa(env);
     mirror::String* s = soa.Decode<mirror::String*>(java_string);
     if (start < 0 || length < 0 || start + length > s->GetLength()) {
@@ -1896,7 +1908,7 @@
 
   static void GetStringUTFRegion(JNIEnv* env, jstring java_string, jsize start, jsize length,
                                  char* buf) {
-    CHECK_NON_NULL_ARGUMENT(java_string);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_string);
     ScopedObjectAccess soa(env);
     mirror::String* s = soa.Decode<mirror::String*>(java_string);
     if (start < 0 || length < 0 || start + length > s->GetLength()) {
@@ -1928,7 +1940,7 @@
   }
 
   static void ReleaseStringChars(JNIEnv* env, jstring java_string, const jchar* chars) {
-    CHECK_NON_NULL_ARGUMENT(java_string);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_string);
     delete[] chars;
     ScopedObjectAccess soa(env);
     UnpinPrimitiveArray(soa, soa.Decode<mirror::String*>(java_string)->GetCharArray());
@@ -1965,7 +1977,7 @@
   }
 
   static jsize GetArrayLength(JNIEnv* env, jarray java_array) {
-    CHECK_NON_NULL_ARGUMENT(java_array);
+    CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(java_array);
     ScopedObjectAccess soa(env);
     mirror::Object* obj = soa.Decode<mirror::Object*>(java_array);
     if (UNLIKELY(!obj->IsArrayInstance())) {
@@ -1985,7 +1997,7 @@
 
   static void SetObjectArrayElement(JNIEnv* env, jobjectArray java_array, jsize index,
                                     jobject java_value) {
-    CHECK_NON_NULL_ARGUMENT(java_array);
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
     ScopedObjectAccess soa(env);
     mirror::ObjectArray<mirror::Object>* array =
         soa.Decode<mirror::ObjectArray<mirror::Object>*>(java_array);
@@ -1994,38 +2006,31 @@
   }
 
   static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
-    ScopedObjectAccess soa(env);
-    return NewPrimitiveArray<jbooleanArray, mirror::BooleanArray>(soa, length);
+    return NewPrimitiveArray<jbooleanArray, mirror::BooleanArray>(env, length);
   }
 
   static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
-    ScopedObjectAccess soa(env);
-    return NewPrimitiveArray<jbyteArray, mirror::ByteArray>(soa, length);
+    return NewPrimitiveArray<jbyteArray, mirror::ByteArray>(env, length);
   }
 
   static jcharArray NewCharArray(JNIEnv* env, jsize length) {
-    ScopedObjectAccess soa(env);
-    return NewPrimitiveArray<jcharArray, mirror::CharArray>(soa, length);
+    return NewPrimitiveArray<jcharArray, mirror::CharArray>(env, length);
   }
 
   static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
-    ScopedObjectAccess soa(env);
-    return NewPrimitiveArray<jdoubleArray, mirror::DoubleArray>(soa, length);
+    return NewPrimitiveArray<jdoubleArray, mirror::DoubleArray>(env, length);
   }
 
   static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
-    ScopedObjectAccess soa(env);
-    return NewPrimitiveArray<jfloatArray, mirror::FloatArray>(soa, length);
+    return NewPrimitiveArray<jfloatArray, mirror::FloatArray>(env, length);
   }
 
   static jintArray NewIntArray(JNIEnv* env, jsize length) {
-    ScopedObjectAccess soa(env);
-    return NewPrimitiveArray<jintArray, mirror::IntArray>(soa, length);
+    return NewPrimitiveArray<jintArray, mirror::IntArray>(env, length);
   }
 
   static jlongArray NewLongArray(JNIEnv* env, jsize length) {
-    ScopedObjectAccess soa(env);
-    return NewPrimitiveArray<jlongArray, mirror::LongArray>(soa, length);
+    return NewPrimitiveArray<jlongArray, mirror::LongArray>(env, length);
   }
 
   static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_jclass,
@@ -2034,6 +2039,7 @@
       JniAbortF("NewObjectArray", "negative array length: %d", length);
       return nullptr;
     }
+    CHECK_NON_NULL_ARGUMENT(element_jclass);
 
     // Compute the array class corresponding to the given element class.
     ScopedObjectAccess soa(env);
@@ -2075,14 +2081,18 @@
   }
 
   static jshortArray NewShortArray(JNIEnv* env, jsize length) {
-    ScopedObjectAccess soa(env);
-    return NewPrimitiveArray<jshortArray, mirror::ShortArray>(soa, length);
+    return NewPrimitiveArray<jshortArray, mirror::ShortArray>(env, length);
   }
 
   static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray java_array, jboolean* is_copy) {
     CHECK_NON_NULL_ARGUMENT(java_array);
     ScopedObjectAccess soa(env);
     mirror::Array* array = soa.Decode<mirror::Array*>(java_array);
+    if (UNLIKELY(!array->GetClass()->IsPrimitiveArray())) {
+      JniAbortF("GetPrimitiveArrayCritical", "expected primitive array, given %s",
+                PrettyDescriptor(array->GetClass()).c_str());
+      return nullptr;
+    }
     gc::Heap* heap = Runtime::Current()->GetHeap();
     if (heap->IsMovableObject(array)) {
       heap->IncrementDisableMovingGC(soa.Self());
@@ -2096,196 +2106,174 @@
     return array->GetRawData(array->GetClass()->GetComponentSize(), 0);
   }
 
-  static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* elements, jint mode) {
-    CHECK_NON_NULL_ARGUMENT(array);
-    ReleasePrimitiveArray(env, array, elements, mode);
+  static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray java_array, void* elements,
+                                            jint mode) {
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
+    ScopedObjectAccess soa(env);
+    mirror::Array* array = soa.Decode<mirror::Array*>(java_array);
+    if (UNLIKELY(!array->GetClass()->IsPrimitiveArray())) {
+      JniAbortF("ReleasePrimitiveArrayCritical", "expected primitive array, given %s",
+                PrettyDescriptor(array->GetClass()).c_str());
+      return;
+    }
+    const size_t component_size = array->GetClass()->GetComponentSize();
+    ReleasePrimitiveArray(soa, array, component_size, elements, mode);
   }
 
   static jboolean* GetBooleanArrayElements(JNIEnv* env, jbooleanArray array, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(array);
-    ScopedObjectAccess soa(env);
-    return GetPrimitiveArray<jbooleanArray, jboolean*, mirror::BooleanArray>(soa, array, is_copy);
+    return GetPrimitiveArray<jbooleanArray, jboolean, mirror::BooleanArray>(env, array, is_copy);
   }
 
   static jbyte* GetByteArrayElements(JNIEnv* env, jbyteArray array, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(array);
-    ScopedObjectAccess soa(env);
-    return GetPrimitiveArray<jbyteArray, jbyte*, mirror::ByteArray>(soa, array, is_copy);
+    return GetPrimitiveArray<jbyteArray, jbyte, mirror::ByteArray>(env, array, is_copy);
   }
 
   static jchar* GetCharArrayElements(JNIEnv* env, jcharArray array, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(array);
-    ScopedObjectAccess soa(env);
-    return GetPrimitiveArray<jcharArray, jchar*, mirror::CharArray>(soa, array, is_copy);
+    return GetPrimitiveArray<jcharArray, jchar, mirror::CharArray>(env, array, is_copy);
   }
 
   static jdouble* GetDoubleArrayElements(JNIEnv* env, jdoubleArray array, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(array);
-    ScopedObjectAccess soa(env);
-    return GetPrimitiveArray<jdoubleArray, jdouble*, mirror::DoubleArray>(soa, array, is_copy);
+    return GetPrimitiveArray<jdoubleArray, jdouble, mirror::DoubleArray>(env, array, is_copy);
   }
 
   static jfloat* GetFloatArrayElements(JNIEnv* env, jfloatArray array, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(array);
-    ScopedObjectAccess soa(env);
-    return GetPrimitiveArray<jfloatArray, jfloat*, mirror::FloatArray>(soa, array, is_copy);
+    return GetPrimitiveArray<jfloatArray, jfloat, mirror::FloatArray>(env, array, is_copy);
   }
 
   static jint* GetIntArrayElements(JNIEnv* env, jintArray array, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(array);
-    ScopedObjectAccess soa(env);
-    return GetPrimitiveArray<jintArray, jint*, mirror::IntArray>(soa, array, is_copy);
+    return GetPrimitiveArray<jintArray, jint, mirror::IntArray>(env, array, is_copy);
   }
 
   static jlong* GetLongArrayElements(JNIEnv* env, jlongArray array, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(array);
-    ScopedObjectAccess soa(env);
-    return GetPrimitiveArray<jlongArray, jlong*, mirror::LongArray>(soa, array, is_copy);
+    return GetPrimitiveArray<jlongArray, jlong, mirror::LongArray>(env, array, is_copy);
   }
 
   static jshort* GetShortArrayElements(JNIEnv* env, jshortArray array, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(array);
-    ScopedObjectAccess soa(env);
-    return GetPrimitiveArray<jshortArray, jshort*, mirror::ShortArray>(soa, array, is_copy);
+    return GetPrimitiveArray<jshortArray, jshort, mirror::ShortArray>(env, array, is_copy);
   }
 
   static void ReleaseBooleanArrayElements(JNIEnv* env, jbooleanArray array, jboolean* elements,
                                           jint mode) {
-    ReleasePrimitiveArray(env, array, elements, mode);
+    ReleasePrimitiveArray<jbooleanArray, jboolean, mirror::BooleanArray>(env, array, elements,
+                                                                         mode);
   }
 
   static void ReleaseByteArrayElements(JNIEnv* env, jbyteArray array, jbyte* elements, jint mode) {
-    ReleasePrimitiveArray(env, array, elements, mode);
+    ReleasePrimitiveArray<jbyteArray, jbyte, mirror::ByteArray>(env, array, elements, mode);
   }
 
   static void ReleaseCharArrayElements(JNIEnv* env, jcharArray array, jchar* elements, jint mode) {
-    ReleasePrimitiveArray(env, array, elements, mode);
+    ReleasePrimitiveArray<jcharArray, jchar, mirror::CharArray>(env, array, elements, mode);
   }
 
   static void ReleaseDoubleArrayElements(JNIEnv* env, jdoubleArray array, jdouble* elements,
                                          jint mode) {
-    ReleasePrimitiveArray(env, array, elements, mode);
+    ReleasePrimitiveArray<jdoubleArray, jdouble, mirror::DoubleArray>(env, array, elements, mode);
   }
 
   static void ReleaseFloatArrayElements(JNIEnv* env, jfloatArray array, jfloat* elements,
                                         jint mode) {
-    ReleasePrimitiveArray(env, array, elements, mode);
+    ReleasePrimitiveArray<jfloatArray, jfloat, mirror::FloatArray>(env, array, elements, mode);
   }
 
   static void ReleaseIntArrayElements(JNIEnv* env, jintArray array, jint* elements, jint mode) {
-    ReleasePrimitiveArray(env, array, elements, mode);
+    ReleasePrimitiveArray<jintArray, jint, mirror::IntArray>(env, array, elements, mode);
   }
 
   static void ReleaseLongArrayElements(JNIEnv* env, jlongArray array, jlong* elements, jint mode) {
-    ReleasePrimitiveArray(env, array, elements, mode);
+    ReleasePrimitiveArray<jlongArray, jlong, mirror::LongArray>(env, array, elements, mode);
   }
 
   static void ReleaseShortArrayElements(JNIEnv* env, jshortArray array, jshort* elements,
                                         jint mode) {
-    ReleasePrimitiveArray(env, array, elements, mode);
+    ReleasePrimitiveArray<jshortArray, jshort, mirror::ShortArray>(env, array, elements, mode);
   }
 
   static void GetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length,
                                     jboolean* buf) {
-    ScopedObjectAccess soa(env);
-    GetPrimitiveArrayRegion<jbooleanArray, jboolean, mirror::BooleanArray>(soa, array, start,
+    GetPrimitiveArrayRegion<jbooleanArray, jboolean, mirror::BooleanArray>(env, array, start,
                                                                            length, buf);
   }
 
   static void GetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length,
                                  jbyte* buf) {
-    ScopedObjectAccess soa(env);
-    GetPrimitiveArrayRegion<jbyteArray, jbyte, mirror::ByteArray>(soa, array, start, length, buf);
+    GetPrimitiveArrayRegion<jbyteArray, jbyte, mirror::ByteArray>(env, array, start, length, buf);
   }
 
   static void GetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length,
                                  jchar* buf) {
-    ScopedObjectAccess soa(env);
-    GetPrimitiveArrayRegion<jcharArray, jchar, mirror::CharArray>(soa, array, start, length, buf);
+    GetPrimitiveArrayRegion<jcharArray, jchar, mirror::CharArray>(env, array, start, length, buf);
   }
 
   static void GetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length,
                                    jdouble* buf) {
-    ScopedObjectAccess soa(env);
-    GetPrimitiveArrayRegion<jdoubleArray, jdouble, mirror::DoubleArray>(soa, array, start, length,
+    GetPrimitiveArrayRegion<jdoubleArray, jdouble, mirror::DoubleArray>(env, array, start, length,
                                                                         buf);
   }
 
   static void GetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length,
                                   jfloat* buf) {
-    ScopedObjectAccess soa(env);
-    GetPrimitiveArrayRegion<jfloatArray, jfloat, mirror::FloatArray>(soa, array, start, length,
+    GetPrimitiveArrayRegion<jfloatArray, jfloat, mirror::FloatArray>(env, array, start, length,
                                                                      buf);
   }
 
   static void GetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length,
                                 jint* buf) {
-    ScopedObjectAccess soa(env);
-    GetPrimitiveArrayRegion<jintArray, jint, mirror::IntArray>(soa, array, start, length, buf);
+    GetPrimitiveArrayRegion<jintArray, jint, mirror::IntArray>(env, array, start, length, buf);
   }
 
   static void GetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length,
                                  jlong* buf) {
-    ScopedObjectAccess soa(env);
-    GetPrimitiveArrayRegion<jlongArray, jlong, mirror::LongArray>(soa, array, start, length, buf);
+    GetPrimitiveArrayRegion<jlongArray, jlong, mirror::LongArray>(env, array, start, length, buf);
   }
 
   static void GetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length,
                                   jshort* buf) {
-    ScopedObjectAccess soa(env);
-    GetPrimitiveArrayRegion<jshortArray, jshort, mirror::ShortArray>(soa, array, start, length,
+    GetPrimitiveArrayRegion<jshortArray, jshort, mirror::ShortArray>(env, array, start, length,
                                                                      buf);
   }
 
   static void SetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length,
                                     const jboolean* buf) {
-    ScopedObjectAccess soa(env);
-    SetPrimitiveArrayRegion<jbooleanArray, jboolean, mirror::BooleanArray>(soa, array, start,
+    SetPrimitiveArrayRegion<jbooleanArray, jboolean, mirror::BooleanArray>(env, array, start,
                                                                            length, buf);
   }
 
   static void SetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length,
                                  const jbyte* buf) {
-    ScopedObjectAccess soa(env);
-    SetPrimitiveArrayRegion<jbyteArray, jbyte, mirror::ByteArray>(soa, array, start, length, buf);
+    SetPrimitiveArrayRegion<jbyteArray, jbyte, mirror::ByteArray>(env, array, start, length, buf);
   }
 
   static void SetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length,
                                  const jchar* buf) {
-    ScopedObjectAccess soa(env);
-    SetPrimitiveArrayRegion<jcharArray, jchar, mirror::CharArray>(soa, array, start, length, buf);
+    SetPrimitiveArrayRegion<jcharArray, jchar, mirror::CharArray>(env, array, start, length, buf);
   }
 
   static void SetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length,
                                    const jdouble* buf) {
-    ScopedObjectAccess soa(env);
-    SetPrimitiveArrayRegion<jdoubleArray, jdouble, mirror::DoubleArray>(soa, array, start, length,
+    SetPrimitiveArrayRegion<jdoubleArray, jdouble, mirror::DoubleArray>(env, array, start, length,
                                                                         buf);
   }
 
   static void SetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length,
                                   const jfloat* buf) {
-    ScopedObjectAccess soa(env);
-    SetPrimitiveArrayRegion<jfloatArray, jfloat, mirror::FloatArray>(soa, array, start, length,
+    SetPrimitiveArrayRegion<jfloatArray, jfloat, mirror::FloatArray>(env, array, start, length,
                                                                      buf);
   }
 
   static void SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length,
                                 const jint* buf) {
-    ScopedObjectAccess soa(env);
-    SetPrimitiveArrayRegion<jintArray, jint, mirror::IntArray>(soa, array, start, length, buf);
+    SetPrimitiveArrayRegion<jintArray, jint, mirror::IntArray>(env, array, start, length, buf);
   }
 
   static void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length,
                                  const jlong* buf) {
-    ScopedObjectAccess soa(env);
-    SetPrimitiveArrayRegion<jlongArray, jlong, mirror::LongArray>(soa, array, start, length, buf);
+    SetPrimitiveArrayRegion<jlongArray, jlong, mirror::LongArray>(env, array, start, length, buf);
   }
 
   static void SetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length,
                                   const jshort* buf) {
-    ScopedObjectAccess soa(env);
-    SetPrimitiveArrayRegion<jshortArray, jshort, mirror::ShortArray>(soa, array, start, length,
+    SetPrimitiveArrayRegion<jshortArray, jshort, mirror::ShortArray>(env, array, start, length,
                                                                      buf);
   }
 
@@ -2300,7 +2288,7 @@
       JniAbortF("RegisterNatives", "negative method count: %d", method_count);
       return JNI_ERR;  // Not reached.
     }
-    CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", java_class);
+    CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", java_class, JNI_ERR);
     ScopedObjectAccess soa(env);
     mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
     if (UNLIKELY(method_count == 0)) {
@@ -2308,7 +2296,7 @@
           << PrettyDescriptor(c);
       return JNI_OK;
     }
-    CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", methods);
+    CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", methods, JNI_ERR);
     for (jint i = 0; i < method_count; ++i) {
       const char* name = methods[i].name;
       const char* sig = methods[i].signature;
@@ -2345,30 +2333,37 @@
   }
 
   static jint UnregisterNatives(JNIEnv* env, jclass java_class) {
-    CHECK_NON_NULL_ARGUMENT(java_class);
+    CHECK_NON_NULL_ARGUMENT_RETURN(java_class, JNI_ERR);
     ScopedObjectAccess soa(env);
     mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
 
     VLOG(jni) << "[Unregistering JNI native methods for " << PrettyClass(c) << "]";
 
+    size_t unregistered_count = 0;
     for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
       mirror::ArtMethod* m = c->GetDirectMethod(i);
       if (m->IsNative()) {
         m->UnregisterNative(soa.Self());
+        unregistered_count++;
       }
     }
     for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
       mirror::ArtMethod* m = c->GetVirtualMethod(i);
       if (m->IsNative()) {
         m->UnregisterNative(soa.Self());
+        unregistered_count++;
       }
     }
 
+    if (unregistered_count == 0) {
+      LOG(WARNING) << "JNI UnregisterNatives: attempt to unregister native methods of class '"
+          << PrettyDescriptor(c) << "' that contains no native methods";
+    }
     return JNI_OK;
   }
 
   static jint MonitorEnter(JNIEnv* env, jobject java_object) NO_THREAD_SAFETY_ANALYSIS {
-    CHECK_NON_NULL_ARGUMENT(java_object);
+    CHECK_NON_NULL_ARGUMENT_RETURN(java_object, JNI_ERR);
     ScopedObjectAccess soa(env);
     mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
     o = o->MonitorEnter(soa.Self());
@@ -2380,7 +2375,7 @@
   }
 
   static jint MonitorExit(JNIEnv* env, jobject java_object) NO_THREAD_SAFETY_ANALYSIS {
-    CHECK_NON_NULL_ARGUMENT(java_object);
+    CHECK_NON_NULL_ARGUMENT_RETURN(java_object, JNI_ERR);
     ScopedObjectAccess soa(env);
     mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
     o->MonitorExit(soa.Self());
@@ -2392,7 +2387,7 @@
   }
 
   static jint GetJavaVM(JNIEnv* env, JavaVM** vm) {
-    CHECK_NON_NULL_ARGUMENT(vm);
+    CHECK_NON_NULL_ARGUMENT_RETURN(vm, JNI_ERR);
     Runtime* runtime = Runtime::Current();
     if (runtime != nullptr) {
       *vm = runtime->GetJavaVM();
@@ -2432,7 +2427,7 @@
   }
 
   static jobjectRefType GetObjectRefType(JNIEnv* env, jobject java_object) {
-    CHECK_NON_NULL_ARGUMENT(java_object);
+    CHECK_NON_NULL_ARGUMENT_RETURN(java_object, JNIInvalidRefType);
 
     // Do we definitely know what kind of reference this is?
     IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
@@ -2479,51 +2474,82 @@
   }
 
   template<typename JniT, typename ArtT>
-  static JniT NewPrimitiveArray(const ScopedObjectAccess& soa, jsize length)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  static JniT NewPrimitiveArray(JNIEnv* env, jsize length) {
     if (UNLIKELY(length < 0)) {
       JniAbortF("NewPrimitiveArray", "negative array length: %d", length);
       return nullptr;
     }
+    ScopedObjectAccess soa(env);
     ArtT* result = ArtT::Alloc(soa.Self(), length);
     return soa.AddLocalReference<JniT>(result);
   }
 
-  template <typename ArrayT, typename CArrayT, typename ArtArrayT>
-  static CArrayT GetPrimitiveArray(ScopedObjectAccess& soa, ArrayT java_array,
-                                   jboolean* is_copy)
+  template <typename JArrayT, typename ElementT, typename ArtArrayT>
+  static ArtArrayT* DecodeAndCheckArrayType(ScopedObjectAccess& soa, JArrayT java_array,
+                                           const char* fn_name, const char* operation)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     ArtArrayT* array = soa.Decode<ArtArrayT*>(java_array);
+    if (UNLIKELY(ArtArrayT::GetArrayClass() != array->GetClass())) {
+      JniAbortF(fn_name, "attempt to %s %s primitive array elements with an object of type %s",
+                operation, PrettyDescriptor(ArtArrayT::GetArrayClass()->GetComponentType()).c_str(),
+                PrettyDescriptor(array->GetClass()).c_str());
+      return nullptr;
+    }
+    DCHECK_EQ(sizeof(ElementT), array->GetClass()->GetComponentSize());
+    return array;
+  }
+
+  template <typename ArrayT, typename ElementT, typename ArtArrayT>
+  static ElementT* GetPrimitiveArray(JNIEnv* env, ArrayT java_array, jboolean* is_copy) {
+    CHECK_NON_NULL_ARGUMENT(java_array);
+    ScopedObjectAccess soa(env);
+    ArtArrayT* array = DecodeAndCheckArrayType<ArrayT, ElementT, ArtArrayT>(soa, java_array,
+                                                                            "GetArrayElements",
+                                                                            "get");
+    if (UNLIKELY(array == nullptr)) {
+      return nullptr;
+    }
     PinPrimitiveArray(soa, array);
     // Only make a copy if necessary.
     if (Runtime::Current()->GetHeap()->IsMovableObject(array)) {
       if (is_copy != nullptr) {
         *is_copy = JNI_TRUE;
       }
-      static const size_t component_size = array->GetClass()->GetComponentSize();
+      const size_t component_size = sizeof(ElementT);
       size_t size = array->GetLength() * component_size;
       void* data = new uint64_t[RoundUp(size, 8) / 8];
       memcpy(data, array->GetData(), size);
-      return reinterpret_cast<CArrayT>(data);
+      return reinterpret_cast<ElementT*>(data);
     } else {
       if (is_copy != nullptr) {
         *is_copy = JNI_FALSE;
       }
-      return reinterpret_cast<CArrayT>(array->GetData());
+      return reinterpret_cast<ElementT*>(array->GetData());
     }
   }
 
-  template <typename ArrayT, typename ElementT>
+  template <typename ArrayT, typename ElementT, typename ArtArrayT>
   static void ReleasePrimitiveArray(JNIEnv* env, ArrayT java_array, ElementT* elements, jint mode) {
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
     ScopedObjectAccess soa(env);
-    mirror::Array* array = soa.Decode<mirror::Array*>(java_array);
-    size_t component_size = array->GetClass()->GetComponentSize();
+    ArtArrayT* array = DecodeAndCheckArrayType<ArrayT, ElementT, ArtArrayT>(soa, java_array,
+                                                                            "ReleaseArrayElements",
+                                                                            "release");
+    if (array == nullptr) {
+      return;
+    }
+    ReleasePrimitiveArray(soa, array, sizeof(ElementT), elements, mode);
+  }
+
+  static void ReleasePrimitiveArray(ScopedObjectAccess& soa, mirror::Array* array,
+                                    size_t component_size, void* elements, jint mode)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     void* array_data = array->GetRawData(component_size, 0);
     gc::Heap* heap = Runtime::Current()->GetHeap();
-    bool is_copy = array_data != reinterpret_cast<void*>(elements);
+    bool is_copy = array_data != elements;
     size_t bytes = array->GetLength() * component_size;
-    VLOG(heap) << "Release primitive array " << env << " array_data " << array_data
-               << " elements " << reinterpret_cast<void*>(elements);
+    VLOG(heap) << "Release primitive array " << soa.Env() << " array_data " << array_data
+               << " elements " << elements;
     if (is_copy) {
       // Sanity check: If elements is not the same as the java array's data, it better not be a
       // heap address. TODO: This might be slow to check, may be worth keeping track of which
@@ -2549,33 +2575,43 @@
     }
   }
 
-  template <typename JavaArrayT, typename JavaT, typename ArrayT>
-  static void GetPrimitiveArrayRegion(ScopedObjectAccess& soa, JavaArrayT java_array,
-                                      jsize start, jsize length, JavaT* buf)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    CHECK_NON_NULL_ARGUMENT(java_array);
-    ArrayT* array = soa.Decode<ArrayT*>(java_array);
-    if (start < 0 || length < 0 || start + length > array->GetLength()) {
-      ThrowAIOOBE(soa, array, start, length, "src");
-    } else {
-      CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf);
-      JavaT* data = array->GetData();
-      memcpy(buf, data + start, length * sizeof(JavaT));
+  template <typename JArrayT, typename ElementT, typename ArtArrayT>
+  static void GetPrimitiveArrayRegion(JNIEnv* env, JArrayT java_array,
+                                      jsize start, jsize length, ElementT* buf) {
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
+    ScopedObjectAccess soa(env);
+    ArtArrayT* array =
+        DecodeAndCheckArrayType<JArrayT, ElementT, ArtArrayT>(soa, java_array,
+                                                              "GetPrimitiveArrayRegion",
+                                                              "get region of");
+    if (array != nullptr) {
+      if (start < 0 || length < 0 || start + length > array->GetLength()) {
+        ThrowAIOOBE(soa, array, start, length, "src");
+      } else {
+        CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf);
+        ElementT* data = array->GetData();
+        memcpy(buf, data + start, length * sizeof(ElementT));
+      }
     }
   }
 
-  template <typename JavaArrayT, typename JavaT, typename ArrayT>
-  static void SetPrimitiveArrayRegion(ScopedObjectAccess& soa, JavaArrayT java_array,
-                                      jsize start, jsize length, const JavaT* buf)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    CHECK_NON_NULL_ARGUMENT(java_array);
-    ArrayT* array = soa.Decode<ArrayT*>(java_array);
-    if (start < 0 || length < 0 || start + length > array->GetLength()) {
-      ThrowAIOOBE(soa, array, start, length, "dst");
-    } else {
-      CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf);
-      JavaT* data = array->GetData();
-      memcpy(data + start, buf, length * sizeof(JavaT));
+  template <typename JArrayT, typename ElementT, typename ArtArrayT>
+  static void SetPrimitiveArrayRegion(JNIEnv* env, JArrayT java_array,
+                                      jsize start, jsize length, const ElementT* buf) {
+    CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
+    ScopedObjectAccess soa(env);
+    ArtArrayT* array =
+        DecodeAndCheckArrayType<JArrayT, ElementT, ArtArrayT>(soa, java_array,
+                                                              "SetPrimitiveArrayRegion",
+                                                              "set region of");
+    if (array != nullptr) {
+      if (start < 0 || length < 0 || start + length > array->GetLength()) {
+        ThrowAIOOBE(soa, array, start, length, "dst");
+      } else {
+        CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf);
+        ElementT* data = array->GetData();
+        memcpy(data + start, buf, length * sizeof(ElementT));
+      }
     }
   }
 };
diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc
index 778b9e5..83e9b10 100644
--- a/runtime/jni_internal_test.cc
+++ b/runtime/jni_internal_test.cc
@@ -33,35 +33,54 @@
     // Turn on -verbose:jni for the JNI tests.
     // gLogVerbosity.jni = true;
 
-    vm_->AttachCurrentThread(&env_, NULL);
+    vm_->AttachCurrentThread(&env_, nullptr);
 
     ScopedLocalRef<jclass> aioobe(env_,
                                   env_->FindClass("java/lang/ArrayIndexOutOfBoundsException"));
-    CHECK(aioobe.get() != NULL);
+    CHECK(aioobe.get() != nullptr);
     aioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(aioobe.get()));
 
     ScopedLocalRef<jclass> ase(env_, env_->FindClass("java/lang/ArrayStoreException"));
-    CHECK(ase.get() != NULL);
+    CHECK(ase.get() != nullptr);
     ase_ = reinterpret_cast<jclass>(env_->NewGlobalRef(ase.get()));
 
     ScopedLocalRef<jclass> sioobe(env_,
                                   env_->FindClass("java/lang/StringIndexOutOfBoundsException"));
-    CHECK(sioobe.get() != NULL);
+    CHECK(sioobe.get() != nullptr);
     sioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(sioobe.get()));
   }
 
+  void ExpectException(jclass exception_class) {
+    EXPECT_TRUE(env_->ExceptionCheck());
+    jthrowable exception = env_->ExceptionOccurred();
+    EXPECT_NE(nullptr, exception);
+    env_->ExceptionClear();
+    EXPECT_TRUE(env_->IsInstanceOf(exception, exception_class));
+  }
+
+  void ExpectClassFound(const char* name) {
+    EXPECT_NE(env_->FindClass(name), nullptr) << name;
+    EXPECT_FALSE(env_->ExceptionCheck()) << name;
+  }
+
+  void ExpectClassNotFound(const char* name) {
+    EXPECT_EQ(env_->FindClass(name), nullptr) << name;
+    EXPECT_TRUE(env_->ExceptionCheck()) << name;
+    env_->ExceptionClear();
+  }
+
   void CleanUpJniEnv() {
-    if (aioobe_ != NULL) {
+    if (aioobe_ != nullptr) {
       env_->DeleteGlobalRef(aioobe_);
-      aioobe_ = NULL;
+      aioobe_ = nullptr;
     }
-    if (ase_ != NULL) {
+    if (ase_ != nullptr) {
       env_->DeleteGlobalRef(ase_);
-      ase_ = NULL;
+      ase_ = nullptr;
     }
-    if (sioobe_ != NULL) {
+    if (sioobe_ != nullptr) {
       env_->DeleteGlobalRef(sioobe_);
-      sioobe_ = NULL;
+      sioobe_ = nullptr;
     }
   }
 
@@ -86,9 +105,9 @@
 
 TEST_F(JniInternalTest, AllocObject) {
   jclass c = env_->FindClass("java/lang/String");
-  ASSERT_TRUE(c != NULL);
+  ASSERT_NE(c, nullptr);
   jobject o = env_->AllocObject(c);
-  ASSERT_TRUE(o != NULL);
+  ASSERT_NE(o, nullptr);
 
   // We have an instance of the class we asked for...
   ASSERT_TRUE(env_->IsInstanceOf(o, c));
@@ -96,139 +115,152 @@
   // we didn't call a constructor.
   ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "count", "I")));
   ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "offset", "I")));
-  ASSERT_TRUE(env_->GetObjectField(o, env_->GetFieldID(c, "value", "[C")) == NULL);
+  ASSERT_TRUE(env_->GetObjectField(o, env_->GetFieldID(c, "value", "[C")) == nullptr);
 }
 
 TEST_F(JniInternalTest, GetVersion) {
   ASSERT_EQ(JNI_VERSION_1_6, env_->GetVersion());
 }
 
-#define EXPECT_CLASS_FOUND(NAME) \
-  EXPECT_TRUE(env_->FindClass(NAME) != NULL); \
-  EXPECT_FALSE(env_->ExceptionCheck())
-
-#define EXPECT_CLASS_NOT_FOUND(NAME) \
-  EXPECT_TRUE(env_->FindClass(NAME) == NULL); \
-  EXPECT_TRUE(env_->ExceptionCheck()); \
-  env_->ExceptionClear()
-
 TEST_F(JniInternalTest, FindClass) {
   // Reference types...
-  EXPECT_CLASS_FOUND("java/lang/String");
+  ExpectClassFound("java/lang/String");
   // ...for arrays too, where you must include "L;".
-  EXPECT_CLASS_FOUND("[Ljava/lang/String;");
+  ExpectClassFound("[Ljava/lang/String;");
   // Primitive arrays are okay too, if the primitive type is valid.
-  EXPECT_CLASS_FOUND("[C");
+  ExpectClassFound("[C");
 
   {
-    // We support . as well as / for compatibility, if -Xcheck:jni is off.
     CheckJniAbortCatcher check_jni_abort_catcher;
-    EXPECT_CLASS_FOUND("java.lang.String");
+    env_->FindClass(nullptr);
+    check_jni_abort_catcher.Check("name == null");
+
+    // We support . as well as / for compatibility, if -Xcheck:jni is off.
+    ExpectClassFound("java.lang.String");
     check_jni_abort_catcher.Check("illegal class name 'java.lang.String'");
-    EXPECT_CLASS_NOT_FOUND("Ljava.lang.String;");
+    ExpectClassNotFound("Ljava.lang.String;");
     check_jni_abort_catcher.Check("illegal class name 'Ljava.lang.String;'");
-    EXPECT_CLASS_FOUND("[Ljava.lang.String;");
+    ExpectClassFound("[Ljava.lang.String;");
     check_jni_abort_catcher.Check("illegal class name '[Ljava.lang.String;'");
-    EXPECT_CLASS_NOT_FOUND("[java.lang.String");
+    ExpectClassNotFound("[java.lang.String");
     check_jni_abort_catcher.Check("illegal class name '[java.lang.String'");
 
     // You can't include the "L;" in a JNI class descriptor.
-    EXPECT_CLASS_NOT_FOUND("Ljava/lang/String;");
+    ExpectClassNotFound("Ljava/lang/String;");
     check_jni_abort_catcher.Check("illegal class name 'Ljava/lang/String;'");
 
     // But you must include it for an array of any reference type.
-    EXPECT_CLASS_NOT_FOUND("[java/lang/String");
+    ExpectClassNotFound("[java/lang/String");
     check_jni_abort_catcher.Check("illegal class name '[java/lang/String'");
 
-    EXPECT_CLASS_NOT_FOUND("[K");
+    ExpectClassNotFound("[K");
     check_jni_abort_catcher.Check("illegal class name '[K'");
+
+    // Void arrays aren't allowed.
+    ExpectClassNotFound("[V");
+    check_jni_abort_catcher.Check("illegal class name '[V'");
   }
 
   // But primitive types aren't allowed...
-  EXPECT_CLASS_NOT_FOUND("C");
-  EXPECT_CLASS_NOT_FOUND("K");
+  ExpectClassNotFound("C");
+  ExpectClassNotFound("V");
+  ExpectClassNotFound("K");
 }
 
-#define EXPECT_EXCEPTION(exception_class) \
-  do { \
-    EXPECT_TRUE(env_->ExceptionCheck()); \
-    jthrowable exception = env_->ExceptionOccurred(); \
-    EXPECT_NE(static_cast<jthrowable>(NULL), exception); \
-    env_->ExceptionClear(); \
-    EXPECT_TRUE(env_->IsInstanceOf(exception, exception_class)); \
-  } while (false)
-
 TEST_F(JniInternalTest, GetFieldID) {
   jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
-  ASSERT_TRUE(jlnsfe != NULL);
+  ASSERT_NE(jlnsfe, nullptr);
   jclass c = env_->FindClass("java/lang/String");
-  ASSERT_TRUE(c != NULL);
+  ASSERT_NE(c, nullptr);
 
   // Wrong type.
   jfieldID fid = env_->GetFieldID(c, "count", "J");
-  EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
-  EXPECT_EXCEPTION(jlnsfe);
+  EXPECT_EQ(nullptr, fid);
+  ExpectException(jlnsfe);
 
   // Wrong type where type doesn't exist.
   fid = env_->GetFieldID(c, "count", "Lrod/jane/freddy;");
-  EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
-  EXPECT_EXCEPTION(jlnsfe);
+  EXPECT_EQ(nullptr, fid);
+  ExpectException(jlnsfe);
 
   // Wrong name.
   fid = env_->GetFieldID(c, "Count", "I");
-  EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
-  EXPECT_EXCEPTION(jlnsfe);
+  EXPECT_EQ(nullptr, fid);
+  ExpectException(jlnsfe);
 
   // Good declared field lookup.
   fid = env_->GetFieldID(c, "count", "I");
-  EXPECT_NE(static_cast<jfieldID>(NULL), fid);
-  EXPECT_TRUE(fid != NULL);
+  EXPECT_NE(nullptr, fid);
   EXPECT_FALSE(env_->ExceptionCheck());
 
   // Good superclass field lookup.
   c = env_->FindClass("java/lang/StringBuilder");
   fid = env_->GetFieldID(c, "count", "I");
-  EXPECT_NE(static_cast<jfieldID>(NULL), fid);
-  EXPECT_TRUE(fid != NULL);
+  EXPECT_NE(nullptr, fid);
+  EXPECT_NE(fid, nullptr);
   EXPECT_FALSE(env_->ExceptionCheck());
 
   // Not instance.
   fid = env_->GetFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
-  EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
-  EXPECT_EXCEPTION(jlnsfe);
+  EXPECT_EQ(nullptr, fid);
+  ExpectException(jlnsfe);
+
+  // Bad arguments.
+  CheckJniAbortCatcher check_jni_abort_catcher;
+  fid = env_->GetFieldID(nullptr, "count", "I");
+  EXPECT_EQ(nullptr, fid);
+  check_jni_abort_catcher.Check("java_class == null");
+  fid = env_->GetFieldID(c, nullptr, "I");
+  EXPECT_EQ(nullptr, fid);
+  check_jni_abort_catcher.Check("name == null");
+  fid = env_->GetFieldID(c, "count", nullptr);
+  EXPECT_EQ(nullptr, fid);
+  check_jni_abort_catcher.Check("sig == null");
 }
 
 TEST_F(JniInternalTest, GetStaticFieldID) {
   jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
-  ASSERT_TRUE(jlnsfe != NULL);
+  ASSERT_NE(jlnsfe, nullptr);
   jclass c = env_->FindClass("java/lang/String");
-  ASSERT_TRUE(c != NULL);
+  ASSERT_NE(c, nullptr);
 
   // Wrong type.
   jfieldID fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "J");
-  EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
-  EXPECT_EXCEPTION(jlnsfe);
+  EXPECT_EQ(nullptr, fid);
+  ExpectException(jlnsfe);
 
   // Wrong type where type doesn't exist.
   fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Lrod/jane/freddy;");
-  EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
-  EXPECT_EXCEPTION(jlnsfe);
+  EXPECT_EQ(nullptr, fid);
+  ExpectException(jlnsfe);
 
   // Wrong name.
   fid = env_->GetStaticFieldID(c, "cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
-  EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
-  EXPECT_EXCEPTION(jlnsfe);
+  EXPECT_EQ(nullptr, fid);
+  ExpectException(jlnsfe);
 
   // Good declared field lookup.
   fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
-  EXPECT_NE(static_cast<jfieldID>(NULL), fid);
-  EXPECT_TRUE(fid != NULL);
+  EXPECT_NE(nullptr, fid);
+  EXPECT_NE(fid, nullptr);
   EXPECT_FALSE(env_->ExceptionCheck());
 
   // Not static.
   fid = env_->GetStaticFieldID(c, "count", "I");
-  EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
-  EXPECT_EXCEPTION(jlnsfe);
+  EXPECT_EQ(nullptr, fid);
+  ExpectException(jlnsfe);
+
+  // Bad arguments.
+  CheckJniAbortCatcher check_jni_abort_catcher;
+  fid = env_->GetStaticFieldID(nullptr, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
+  EXPECT_EQ(nullptr, fid);
+  check_jni_abort_catcher.Check("java_class == null");
+  fid = env_->GetStaticFieldID(c, nullptr, "Ljava/util/Comparator;");
+  EXPECT_EQ(nullptr, fid);
+  check_jni_abort_catcher.Check("name == null");
+  fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", nullptr);
+  EXPECT_EQ(nullptr, fid);
+  check_jni_abort_catcher.Check("sig == null");
 }
 
 TEST_F(JniInternalTest, GetMethodID) {
@@ -242,24 +274,36 @@
   // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
   // a pending exception
   jmethodID method = env_->GetMethodID(jlobject, "foo", "()V");
-  EXPECT_EQ(static_cast<jmethodID>(NULL), method);
-  EXPECT_EXCEPTION(jlnsme);
+  EXPECT_EQ(nullptr, method);
+  ExpectException(jlnsme);
 
   // Check that java.lang.Object.equals() does exist
   method = env_->GetMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
-  EXPECT_NE(static_cast<jmethodID>(NULL), method);
+  EXPECT_NE(nullptr, method);
   EXPECT_FALSE(env_->ExceptionCheck());
 
   // Check that GetMethodID for java.lang.String.valueOf(int) fails as the
   // method is static
   method = env_->GetMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
-  EXPECT_EQ(static_cast<jmethodID>(NULL), method);
-  EXPECT_EXCEPTION(jlnsme);
+  EXPECT_EQ(nullptr, method);
+  ExpectException(jlnsme);
 
   // Check that GetMethodID for java.lang.NoSuchMethodError.<init>(String) finds the constructor
   method = env_->GetMethodID(jlnsme, "<init>", "(Ljava/lang/String;)V");
-  EXPECT_NE(static_cast<jmethodID>(NULL), method);
+  EXPECT_NE(nullptr, method);
   EXPECT_FALSE(env_->ExceptionCheck());
+
+  // Bad arguments.
+  CheckJniAbortCatcher check_jni_abort_catcher;
+  method = env_->GetMethodID(nullptr, "<init>", "(Ljava/lang/String;)V");
+  EXPECT_EQ(nullptr, method);
+  check_jni_abort_catcher.Check("java_class == null");
+  method = env_->GetMethodID(jlnsme, nullptr, "(Ljava/lang/String;)V");
+  EXPECT_EQ(nullptr, method);
+  check_jni_abort_catcher.Check("name == null");
+  method = env_->GetMethodID(jlnsme, "<init>", nullptr);
+  EXPECT_EQ(nullptr, method);
+  check_jni_abort_catcher.Check("sig == null");
 }
 
 TEST_F(JniInternalTest, GetStaticMethodID) {
@@ -272,93 +316,155 @@
   // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
   // a pending exception
   jmethodID method = env_->GetStaticMethodID(jlobject, "foo", "()V");
-  EXPECT_EQ(static_cast<jmethodID>(NULL), method);
-  EXPECT_EXCEPTION(jlnsme);
+  EXPECT_EQ(nullptr, method);
+  ExpectException(jlnsme);
 
   // Check that GetStaticMethodID for java.lang.Object.equals(Object) fails as
   // the method is not static
   method = env_->GetStaticMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
-  EXPECT_EQ(static_cast<jmethodID>(NULL), method);
-  EXPECT_EXCEPTION(jlnsme);
+  EXPECT_EQ(nullptr, method);
+  ExpectException(jlnsme);
 
   // Check that java.lang.String.valueOf(int) does exist
   jclass jlstring = env_->FindClass("java/lang/String");
-  method = env_->GetStaticMethodID(jlstring, "valueOf",
-                                   "(I)Ljava/lang/String;");
-  EXPECT_NE(static_cast<jmethodID>(NULL), method);
+  method = env_->GetStaticMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
+  EXPECT_NE(nullptr, method);
   EXPECT_FALSE(env_->ExceptionCheck());
+
+  // Bad arguments.
+  CheckJniAbortCatcher check_jni_abort_catcher;
+  method = env_->GetStaticMethodID(nullptr, "valueOf", "(I)Ljava/lang/String;");
+  EXPECT_EQ(nullptr, method);
+  check_jni_abort_catcher.Check("java_class == null");
+  method = env_->GetStaticMethodID(jlstring, nullptr, "(I)Ljava/lang/String;");
+  EXPECT_EQ(nullptr, method);
+  check_jni_abort_catcher.Check("name == null");
+  method = env_->GetStaticMethodID(jlstring, "valueOf", nullptr);
+  EXPECT_EQ(nullptr, method);
+  check_jni_abort_catcher.Check("sig == null");
 }
 
 TEST_F(JniInternalTest, FromReflectedField_ToReflectedField) {
   jclass jlrField = env_->FindClass("java/lang/reflect/Field");
   jclass c = env_->FindClass("java/lang/String");
-  ASSERT_TRUE(c != NULL);
+  ASSERT_NE(c, nullptr);
   jfieldID fid = env_->GetFieldID(c, "count", "I");
-  ASSERT_TRUE(fid != NULL);
+  ASSERT_NE(fid, nullptr);
   // Turn the fid into a java.lang.reflect.Field...
   jobject field = env_->ToReflectedField(c, fid, JNI_FALSE);
-  ASSERT_TRUE(c != NULL);
+  ASSERT_NE(c, nullptr);
   ASSERT_TRUE(env_->IsInstanceOf(field, jlrField));
   // ...and back again.
   jfieldID fid2 = env_->FromReflectedField(field);
-  ASSERT_TRUE(fid2 != NULL);
+  ASSERT_NE(fid2, nullptr);
   // Make sure we can actually use it.
   jstring s = env_->NewStringUTF("poop");
   ASSERT_EQ(4, env_->GetIntField(s, fid2));
+
+  // Bad arguments.
+  CheckJniAbortCatcher check_jni_abort_catcher;
+  field = env_->ToReflectedField(c, nullptr, JNI_FALSE);
+  EXPECT_EQ(field, nullptr);
+  check_jni_abort_catcher.Check("fid == null");
+  fid2 = env_->FromReflectedField(nullptr);
+  ASSERT_EQ(fid2, nullptr);
+  check_jni_abort_catcher.Check("jlr_field == null");
 }
 
 TEST_F(JniInternalTest, FromReflectedMethod_ToReflectedMethod) {
   jclass jlrMethod = env_->FindClass("java/lang/reflect/Method");
   jclass c = env_->FindClass("java/lang/String");
-  ASSERT_TRUE(c != NULL);
+  ASSERT_NE(c, nullptr);
   jmethodID mid = env_->GetMethodID(c, "length", "()I");
-  ASSERT_TRUE(mid != NULL);
+  ASSERT_NE(mid, nullptr);
   // Turn the mid into a java.lang.reflect.Method...
   jobject method = env_->ToReflectedMethod(c, mid, JNI_FALSE);
-  ASSERT_TRUE(c != NULL);
+  ASSERT_NE(c, nullptr);
   ASSERT_TRUE(env_->IsInstanceOf(method, jlrMethod));
   // ...and back again.
   jmethodID mid2 = env_->FromReflectedMethod(method);
-  ASSERT_TRUE(mid2 != NULL);
+  ASSERT_NE(mid2, nullptr);
   // Make sure we can actually use it.
   jstring s = env_->NewStringUTF("poop");
   ASSERT_EQ(4, env_->CallIntMethod(s, mid2));
+
+  // Bad arguments.
+  CheckJniAbortCatcher check_jni_abort_catcher;
+  method = env_->ToReflectedMethod(c, nullptr, JNI_FALSE);
+  EXPECT_EQ(method, nullptr);
+  check_jni_abort_catcher.Check("mid == null");
+  mid2 = env_->FromReflectedMethod(method);
+  ASSERT_EQ(mid2, nullptr);
+  check_jni_abort_catcher.Check("jlr_method == null");
 }
 
-void BogusMethod() {
-  // You can't pass NULL function pointers to RegisterNatives.
+static void BogusMethod() {
+  // You can't pass nullptr function pointers to RegisterNatives.
 }
 
-TEST_F(JniInternalTest, RegisterNatives) {
+TEST_F(JniInternalTest, RegisterAndUnregisterNatives) {
   jclass jlobject = env_->FindClass("java/lang/Object");
   jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
 
-  // Sanity check that no exceptions are pending
+  // Sanity check that no exceptions are pending.
   ASSERT_FALSE(env_->ExceptionCheck());
 
-  // Check that registering to a non-existent java.lang.Object.foo() causes a
-  // NoSuchMethodError
+  // Check that registering to a non-existent java.lang.Object.foo() causes a NoSuchMethodError.
   {
-    JNINativeMethod methods[] = { { "foo", "()V", NULL } };
-    env_->RegisterNatives(jlobject, methods, 1);
+    JNINativeMethod methods[] = { { "foo", "()V", nullptr } };
+    EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
   }
-  EXPECT_EXCEPTION(jlnsme);
+  ExpectException(jlnsme);
 
-  // Check that registering non-native methods causes a NoSuchMethodError
+  // Check that registering non-native methods causes a NoSuchMethodError.
   {
-    JNINativeMethod methods[] = { { "equals", "(Ljava/lang/Object;)Z", NULL } };
-    env_->RegisterNatives(jlobject, methods, 1);
+    JNINativeMethod methods[] = { { "equals", "(Ljava/lang/Object;)Z", nullptr } };
+    EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
   }
-  EXPECT_EXCEPTION(jlnsme);
+  ExpectException(jlnsme);
 
-  // Check that registering native methods is successful
+  // Check that registering native methods is successful.
   {
     JNINativeMethod methods[] = { { "notify", "()V", reinterpret_cast<void*>(BogusMethod) } };
-    env_->RegisterNatives(jlobject, methods, 1);
+    EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_OK);
+  }
+  EXPECT_FALSE(env_->ExceptionCheck());
+  EXPECT_EQ(env_->UnregisterNatives(jlobject), JNI_OK);
+
+  // Check that registering no methods isn't a failure.
+  {
+    JNINativeMethod methods[] = { };
+    EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 0), JNI_OK);
+  }
+  EXPECT_FALSE(env_->ExceptionCheck());
+  EXPECT_EQ(env_->UnregisterNatives(jlobject), JNI_OK);
+
+  // Check that registering a -ve number of methods is a failure.
+  CheckJniAbortCatcher check_jni_abort_catcher;
+  for (int i = -10; i < 0; ++i) {
+    JNINativeMethod methods[] = { };
+    EXPECT_EQ(env_->RegisterNatives(jlobject, methods, i), JNI_ERR);
+    check_jni_abort_catcher.Check("negative method count: ");
   }
   EXPECT_FALSE(env_->ExceptionCheck());
 
-  env_->UnregisterNatives(jlobject);
+  // Passing a class of null is a failure.
+  {
+    JNINativeMethod methods[] = { };
+    EXPECT_EQ(env_->RegisterNatives(nullptr, methods, 0), JNI_ERR);
+    check_jni_abort_catcher.Check("java_class == null");
+  }
+
+  // Passing methods as null is a failure.
+  EXPECT_EQ(env_->RegisterNatives(jlobject, nullptr, 1), JNI_ERR);
+  check_jni_abort_catcher.Check("methods == null");
+
+  // Unregisters null is a failure.
+  EXPECT_EQ(env_->UnregisterNatives(nullptr), JNI_ERR);
+  check_jni_abort_catcher.Check("java_class == null");
+
+  // Unregistering a class with no natives is a warning.
+  EXPECT_EQ(env_->UnregisterNatives(jlnsme), JNI_OK);
 }
 
 #define EXPECT_PRIMITIVE_ARRAY(new_fn, \
@@ -368,52 +474,69 @@
                                release_elements_fn, \
                                scalar_type, \
                                expected_class_descriptor) \
+  jsize size = 4; \
+  \
   { \
     CheckJniAbortCatcher jni_abort_catcher; \
     /* Allocate an negative sized array and check it has the right failure type. */ \
-    env_->new_fn(-1); \
+    EXPECT_EQ(env_->new_fn(-1), nullptr); \
     jni_abort_catcher.Check("negative array length: -1"); \
-    env_->new_fn(std::numeric_limits<jint>::min()); \
+    EXPECT_EQ(env_->new_fn(std::numeric_limits<jint>::min()), nullptr); \
     jni_abort_catcher.Check("negative array length: -2147483648"); \
+    /* Pass the array as null. */ \
+    EXPECT_EQ(0, env_->GetArrayLength(nullptr)); \
+    jni_abort_catcher.Check("java_array == null"); \
+    env_->get_region_fn(nullptr, 0, 0, nullptr); \
+    jni_abort_catcher.Check("java_array == null"); \
+    env_->set_region_fn(nullptr, 0, 0, nullptr); \
+    jni_abort_catcher.Check("java_array == null"); \
+    env_->get_elements_fn(nullptr, nullptr); \
+    jni_abort_catcher.Check("java_array == null"); \
+    env_->release_elements_fn(nullptr, nullptr, 0); \
+    jni_abort_catcher.Check("java_array == null"); \
+    /* Pass the elements for region as null. */ \
+    scalar_type ## Array a = env_->new_fn(size); \
+    env_->get_region_fn(a, 0, size, nullptr); \
+    jni_abort_catcher.Check("buf == null"); \
+    env_->set_region_fn(a, 0, size, nullptr); \
+    jni_abort_catcher.Check("buf == null"); \
   } \
-  jsize size = 4; \
-  \
   /* Allocate an array and check it has the right type and length. */ \
   scalar_type ## Array a = env_->new_fn(size); \
-  EXPECT_TRUE(a != NULL); \
+  EXPECT_NE(a, nullptr); \
   EXPECT_TRUE(env_->IsInstanceOf(a, env_->FindClass(expected_class_descriptor))); \
   EXPECT_EQ(size, env_->GetArrayLength(a)); \
   \
   /* GetPrimitiveArrayRegion/SetPrimitiveArrayRegion */ \
   /* AIOOBE for negative start offset. */ \
-  env_->get_region_fn(a, -1, 1, NULL); \
-  EXPECT_EXCEPTION(aioobe_); \
-  env_->set_region_fn(a, -1, 1, NULL); \
-  EXPECT_EXCEPTION(aioobe_); \
+  env_->get_region_fn(a, -1, 1, nullptr); \
+  ExpectException(aioobe_); \
+  env_->set_region_fn(a, -1, 1, nullptr); \
+  ExpectException(aioobe_); \
   \
   /* AIOOBE for negative length. */ \
-  env_->get_region_fn(a, 0, -1, NULL); \
-  EXPECT_EXCEPTION(aioobe_); \
-  env_->set_region_fn(a, 0, -1, NULL); \
-  EXPECT_EXCEPTION(aioobe_); \
+  env_->get_region_fn(a, 0, -1, nullptr); \
+  ExpectException(aioobe_); \
+  env_->set_region_fn(a, 0, -1, nullptr); \
+  ExpectException(aioobe_); \
   \
   /* AIOOBE for buffer overrun. */ \
-  env_->get_region_fn(a, size - 1, size, NULL); \
-  EXPECT_EXCEPTION(aioobe_); \
-  env_->set_region_fn(a, size - 1, size, NULL); \
-  EXPECT_EXCEPTION(aioobe_); \
+  env_->get_region_fn(a, size - 1, size, nullptr); \
+  ExpectException(aioobe_); \
+  env_->set_region_fn(a, size - 1, size, nullptr); \
+  ExpectException(aioobe_); \
   \
-  /* It's okay for the buffer to be NULL as long as the length is 0. */ \
-  env_->get_region_fn(a, 2, 0, NULL); \
+  /* It's okay for the buffer to be nullptr as long as the length is 0. */ \
+  env_->get_region_fn(a, 2, 0, nullptr); \
   /* Even if the offset is invalid... */ \
-  env_->get_region_fn(a, 123, 0, NULL); \
-  EXPECT_EXCEPTION(aioobe_); \
+  env_->get_region_fn(a, 123, 0, nullptr); \
+  ExpectException(aioobe_); \
   \
-  /* It's okay for the buffer to be NULL as long as the length is 0. */ \
-  env_->set_region_fn(a, 2, 0, NULL); \
+  /* It's okay for the buffer to be nullptr as long as the length is 0. */ \
+  env_->set_region_fn(a, 2, 0, nullptr); \
   /* Even if the offset is invalid... */ \
-  env_->set_region_fn(a, 123, 0, NULL); \
-  EXPECT_EXCEPTION(aioobe_); \
+  env_->set_region_fn(a, 123, 0, nullptr); \
+  ExpectException(aioobe_); \
   \
   /* Prepare a couple of buffers. */ \
   UniquePtr<scalar_type[]> src_buf(new scalar_type[size]); \
@@ -437,12 +560,12 @@
   EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
     << "full copy not equal"; \
   /* GetPrimitiveArrayCritical */ \
-  void* v = env_->GetPrimitiveArrayCritical(a, NULL); \
+  void* v = env_->GetPrimitiveArrayCritical(a, nullptr); \
   EXPECT_EQ(memcmp(&src_buf[0], v, size * sizeof(scalar_type)), 0) \
     << "GetPrimitiveArrayCritical not equal"; \
   env_->ReleasePrimitiveArrayCritical(a, v, 0); \
   /* GetXArrayElements */ \
-  scalar_type* xs = env_->get_elements_fn(a, NULL); \
+  scalar_type* xs = env_->get_elements_fn(a, nullptr); \
   EXPECT_EQ(memcmp(&src_buf[0], xs, size * sizeof(scalar_type)), 0) \
     << # get_elements_fn " not equal"; \
   env_->release_elements_fn(a, xs, 0); \
@@ -480,31 +603,206 @@
                          GetShortArrayElements, ReleaseShortArrayElements, jshort, "[S");
 }
 
+TEST_F(JniInternalTest, GetPrimitiveArrayElementsOfWrongType) {
+  CheckJniAbortCatcher jni_abort_catcher;
+  jbooleanArray array = env_->NewBooleanArray(10);
+  jboolean is_copy;
+  EXPECT_EQ(env_->GetByteArrayElements(reinterpret_cast<jbyteArray>(array), &is_copy), nullptr);
+  jni_abort_catcher.Check(
+      "attempt to get byte primitive array elements with an object of type boolean[]");
+  EXPECT_EQ(env_->GetShortArrayElements(reinterpret_cast<jshortArray>(array), &is_copy), nullptr);
+  jni_abort_catcher.Check(
+      "attempt to get short primitive array elements with an object of type boolean[]");
+  EXPECT_EQ(env_->GetCharArrayElements(reinterpret_cast<jcharArray>(array), &is_copy), nullptr);
+  jni_abort_catcher.Check(
+      "attempt to get char primitive array elements with an object of type boolean[]");
+  EXPECT_EQ(env_->GetIntArrayElements(reinterpret_cast<jintArray>(array), &is_copy), nullptr);
+  jni_abort_catcher.Check(
+      "attempt to get int primitive array elements with an object of type boolean[]");
+  EXPECT_EQ(env_->GetLongArrayElements(reinterpret_cast<jlongArray>(array), &is_copy), nullptr);
+  jni_abort_catcher.Check(
+      "attempt to get long primitive array elements with an object of type boolean[]");
+  EXPECT_EQ(env_->GetFloatArrayElements(reinterpret_cast<jfloatArray>(array), &is_copy), nullptr);
+  jni_abort_catcher.Check(
+      "attempt to get float primitive array elements with an object of type boolean[]");
+  EXPECT_EQ(env_->GetDoubleArrayElements(reinterpret_cast<jdoubleArray>(array), &is_copy), nullptr);
+  jni_abort_catcher.Check(
+      "attempt to get double primitive array elements with an object of type boolean[]");
+  jbyteArray array2 = env_->NewByteArray(10);
+  EXPECT_EQ(env_->GetBooleanArrayElements(reinterpret_cast<jbooleanArray>(array2), &is_copy), nullptr);
+  jni_abort_catcher.Check(
+      "attempt to get boolean primitive array elements with an object of type byte[]");
+  jobject object = env_->NewStringUTF("Test String");
+  EXPECT_EQ(env_->GetBooleanArrayElements(reinterpret_cast<jbooleanArray>(object), &is_copy), nullptr);
+  jni_abort_catcher.Check(
+      "attempt to get boolean primitive array elements with an object of type java.lang.String");
+}
+
+TEST_F(JniInternalTest, ReleasePrimitiveArrayElementsOfWrongType) {
+  CheckJniAbortCatcher jni_abort_catcher;
+  jbooleanArray array = env_->NewBooleanArray(10);
+  ASSERT_TRUE(array != nullptr);
+  jboolean is_copy;
+  jboolean* elements = env_->GetBooleanArrayElements(array, &is_copy);
+  ASSERT_TRUE(elements != nullptr);
+  env_->ReleaseByteArrayElements(reinterpret_cast<jbyteArray>(array),
+                                 reinterpret_cast<jbyte*>(elements), 0);
+  jni_abort_catcher.Check(
+      "attempt to release byte primitive array elements with an object of type boolean[]");
+  env_->ReleaseShortArrayElements(reinterpret_cast<jshortArray>(array),
+                                  reinterpret_cast<jshort*>(elements), 0);
+  jni_abort_catcher.Check(
+      "attempt to release short primitive array elements with an object of type boolean[]");
+  env_->ReleaseCharArrayElements(reinterpret_cast<jcharArray>(array),
+                                 reinterpret_cast<jchar*>(elements), 0);
+  jni_abort_catcher.Check(
+      "attempt to release char primitive array elements with an object of type boolean[]");
+  env_->ReleaseIntArrayElements(reinterpret_cast<jintArray>(array),
+                                reinterpret_cast<jint*>(elements), 0);
+  jni_abort_catcher.Check(
+      "attempt to release int primitive array elements with an object of type boolean[]");
+  env_->ReleaseLongArrayElements(reinterpret_cast<jlongArray>(array),
+                                 reinterpret_cast<jlong*>(elements), 0);
+  jni_abort_catcher.Check(
+      "attempt to release long primitive array elements with an object of type boolean[]");
+  env_->ReleaseFloatArrayElements(reinterpret_cast<jfloatArray>(array),
+                                  reinterpret_cast<jfloat*>(elements), 0);
+  jni_abort_catcher.Check(
+      "attempt to release float primitive array elements with an object of type boolean[]");
+  env_->ReleaseDoubleArrayElements(reinterpret_cast<jdoubleArray>(array),
+                                  reinterpret_cast<jdouble*>(elements), 0);
+  jni_abort_catcher.Check(
+      "attempt to release double primitive array elements with an object of type boolean[]");
+  jbyteArray array2 = env_->NewByteArray(10);
+  env_->ReleaseBooleanArrayElements(reinterpret_cast<jbooleanArray>(array2), elements, 0);
+  jni_abort_catcher.Check(
+      "attempt to release boolean primitive array elements with an object of type byte[]");
+  jobject object = env_->NewStringUTF("Test String");
+  env_->ReleaseBooleanArrayElements(reinterpret_cast<jbooleanArray>(object), elements, 0);
+  jni_abort_catcher.Check(
+      "attempt to release boolean primitive array elements with an object of type java.lang.String");
+}
+TEST_F(JniInternalTest, GetReleasePrimitiveArrayCriticalOfWrongType) {
+  CheckJniAbortCatcher jni_abort_catcher;
+  jobject object = env_->NewStringUTF("Test String");
+  jboolean is_copy;
+  void* elements = env_->GetPrimitiveArrayCritical(reinterpret_cast<jarray>(object), &is_copy);
+  jni_abort_catcher.Check("expected primitive array, given java.lang.String");
+  env_->ReleasePrimitiveArrayCritical(reinterpret_cast<jarray>(object), elements, 0);
+  jni_abort_catcher.Check("expected primitive array, given java.lang.String");
+}
+
+TEST_F(JniInternalTest, GetPrimitiveArrayRegionElementsOfWrongType) {
+  CheckJniAbortCatcher jni_abort_catcher;
+  constexpr size_t kLength = 10;
+  jbooleanArray array = env_->NewBooleanArray(kLength);
+  ASSERT_TRUE(array != nullptr);
+  jboolean elements[kLength];
+  env_->GetByteArrayRegion(reinterpret_cast<jbyteArray>(array), 0, kLength,
+                           reinterpret_cast<jbyte*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to get region of byte primitive array elements with an object of type boolean[]");
+  env_->GetShortArrayRegion(reinterpret_cast<jshortArray>(array), 0, kLength,
+                            reinterpret_cast<jshort*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to get region of short primitive array elements with an object of type boolean[]");
+  env_->GetCharArrayRegion(reinterpret_cast<jcharArray>(array), 0, kLength,
+                           reinterpret_cast<jchar*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to get region of char primitive array elements with an object of type boolean[]");
+  env_->GetIntArrayRegion(reinterpret_cast<jintArray>(array), 0, kLength,
+                          reinterpret_cast<jint*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to get region of int primitive array elements with an object of type boolean[]");
+  env_->GetLongArrayRegion(reinterpret_cast<jlongArray>(array), 0, kLength,
+                           reinterpret_cast<jlong*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to get region of long primitive array elements with an object of type boolean[]");
+  env_->GetFloatArrayRegion(reinterpret_cast<jfloatArray>(array), 0, kLength,
+                            reinterpret_cast<jfloat*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to get region of float primitive array elements with an object of type boolean[]");
+  env_->GetDoubleArrayRegion(reinterpret_cast<jdoubleArray>(array), 0, kLength,
+                           reinterpret_cast<jdouble*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to get region of double primitive array elements with an object of type boolean[]");
+  jbyteArray array2 = env_->NewByteArray(10);
+  env_->GetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(array2), 0, kLength,
+                              reinterpret_cast<jboolean*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to get region of boolean primitive array elements with an object of type byte[]");
+  jobject object = env_->NewStringUTF("Test String");
+  env_->GetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(object), 0, kLength,
+                              reinterpret_cast<jboolean*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to get region of boolean primitive array elements with an object of type java.lang.String");
+}
+
+TEST_F(JniInternalTest, SetPrimitiveArrayRegionElementsOfWrongType) {
+  CheckJniAbortCatcher jni_abort_catcher;
+  constexpr size_t kLength = 10;
+  jbooleanArray array = env_->NewBooleanArray(kLength);
+  ASSERT_TRUE(array != nullptr);
+  jboolean elements[kLength];
+  env_->SetByteArrayRegion(reinterpret_cast<jbyteArray>(array), 0, kLength,
+                           reinterpret_cast<jbyte*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to set region of byte primitive array elements with an object of type boolean[]");
+  env_->SetShortArrayRegion(reinterpret_cast<jshortArray>(array), 0, kLength,
+                            reinterpret_cast<jshort*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to set region of short primitive array elements with an object of type boolean[]");
+  env_->SetCharArrayRegion(reinterpret_cast<jcharArray>(array), 0, kLength,
+                           reinterpret_cast<jchar*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to set region of char primitive array elements with an object of type boolean[]");
+  env_->SetIntArrayRegion(reinterpret_cast<jintArray>(array), 0, kLength,
+                          reinterpret_cast<jint*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to set region of int primitive array elements with an object of type boolean[]");
+  env_->SetLongArrayRegion(reinterpret_cast<jlongArray>(array), 0, kLength,
+                           reinterpret_cast<jlong*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to set region of long primitive array elements with an object of type boolean[]");
+  env_->SetFloatArrayRegion(reinterpret_cast<jfloatArray>(array), 0, kLength,
+                            reinterpret_cast<jfloat*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to set region of float primitive array elements with an object of type boolean[]");
+  env_->SetDoubleArrayRegion(reinterpret_cast<jdoubleArray>(array), 0, kLength,
+                           reinterpret_cast<jdouble*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to set region of double primitive array elements with an object of type boolean[]");
+  jbyteArray array2 = env_->NewByteArray(10);
+  env_->SetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(array2), 0, kLength,
+                              reinterpret_cast<jboolean*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to set region of boolean primitive array elements with an object of type byte[]");
+  jobject object = env_->NewStringUTF("Test String");
+  env_->SetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(object), 0, kLength,
+                              reinterpret_cast<jboolean*>(elements));
+  jni_abort_catcher.Check(
+      "attempt to set region of boolean primitive array elements with an object of type java.lang.String");
+}
+
 TEST_F(JniInternalTest, NewObjectArray) {
   jclass element_class = env_->FindClass("java/lang/String");
-  ASSERT_TRUE(element_class != nullptr);
+  ASSERT_NE(element_class, nullptr);
   jclass array_class = env_->FindClass("[Ljava/lang/String;");
-  ASSERT_TRUE(array_class != nullptr);
+  ASSERT_NE(array_class, nullptr);
 
   jobjectArray a = env_->NewObjectArray(0, element_class, nullptr);
-  EXPECT_TRUE(a != nullptr);
+  EXPECT_NE(a, nullptr);
   EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
   EXPECT_EQ(0, env_->GetArrayLength(a));
 
   a = env_->NewObjectArray(1, element_class, nullptr);
-  EXPECT_TRUE(a != nullptr);
+  EXPECT_NE(a, nullptr);
   EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
   EXPECT_EQ(1, env_->GetArrayLength(a));
   EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), nullptr));
-}
 
-TEST_F(JniInternalTest, NewObjectArrayWithNegativeLength) {
-  jclass element_class = env_->FindClass("java/lang/String");
-  ASSERT_TRUE(element_class != nullptr);
-  jclass array_class = env_->FindClass("[Ljava/lang/String;");
-  ASSERT_TRUE(array_class != nullptr);
+  // Negative array length checks.
   CheckJniAbortCatcher jni_abort_catcher;
-
   env_->NewObjectArray(-1, element_class, nullptr);
   jni_abort_catcher.Check("negative array length: -1");
 
@@ -521,6 +819,8 @@
 
   CheckJniAbortCatcher jni_abort_catcher;
   for (size_t i = 0; i < strlen(primitive_descriptors); ++i) {
+    env_->NewObjectArray(0, nullptr, nullptr);
+    jni_abort_catcher.Check("element_jclass == null");
     jclass primitive_class = GetPrimitiveClass(primitive_descriptors[i]);
     env_->NewObjectArray(1, primitive_class, nullptr);
     std::string error_msg(StringPrintf("not an object type: %s", primitive_names[i]));
@@ -530,13 +830,13 @@
 
 TEST_F(JniInternalTest, NewObjectArrayWithInitialValue) {
   jclass element_class = env_->FindClass("java/lang/String");
-  ASSERT_TRUE(element_class != nullptr);
+  ASSERT_NE(element_class, nullptr);
   jclass array_class = env_->FindClass("[Ljava/lang/String;");
-  ASSERT_TRUE(array_class != nullptr);
+  ASSERT_NE(array_class, nullptr);
 
   jstring s = env_->NewStringUTF("poop");
   jobjectArray a = env_->NewObjectArray(2, element_class, s);
-  EXPECT_TRUE(a != nullptr);
+  EXPECT_NE(a, nullptr);
   EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
   EXPECT_EQ(2, env_->GetArrayLength(a));
   EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), s));
@@ -555,9 +855,9 @@
 
 TEST_F(JniInternalTest, GetObjectClass) {
   jclass string_class = env_->FindClass("java/lang/String");
-  ASSERT_TRUE(string_class != NULL);
+  ASSERT_NE(string_class, nullptr);
   jclass class_class = env_->FindClass("java/lang/Class");
-  ASSERT_TRUE(class_class != NULL);
+  ASSERT_NE(class_class, nullptr);
 
   jstring s = env_->NewStringUTF("poop");
   jclass c = env_->GetObjectClass(s);
@@ -565,33 +865,50 @@
 
   jclass c2 = env_->GetObjectClass(c);
   ASSERT_TRUE(env_->IsSameObject(class_class, env_->GetObjectClass(c2)));
+
+  // Null as object should fail.
+  CheckJniAbortCatcher jni_abort_catcher;
+  EXPECT_EQ(env_->GetObjectClass(nullptr), nullptr);
+  jni_abort_catcher.Check("java_object == null");
 }
 
 TEST_F(JniInternalTest, GetSuperclass) {
   jclass object_class = env_->FindClass("java/lang/Object");
-  ASSERT_TRUE(object_class != NULL);
+  ASSERT_NE(object_class, nullptr);
   jclass string_class = env_->FindClass("java/lang/String");
-  ASSERT_TRUE(string_class != NULL);
+  ASSERT_NE(string_class, nullptr);
   jclass runnable_interface = env_->FindClass("java/lang/Runnable");
-  ASSERT_TRUE(runnable_interface != NULL);
+  ASSERT_NE(runnable_interface, nullptr);
   ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(string_class)));
-  ASSERT_TRUE(env_->GetSuperclass(object_class) == NULL);
+  ASSERT_EQ(env_->GetSuperclass(object_class), nullptr);
   ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(runnable_interface)));
+
+  // Null as class should fail.
+  CheckJniAbortCatcher jni_abort_catcher;
+  EXPECT_EQ(env_->GetSuperclass(nullptr), nullptr);
+  jni_abort_catcher.Check("java_class == null");
 }
 
 TEST_F(JniInternalTest, IsAssignableFrom) {
   jclass object_class = env_->FindClass("java/lang/Object");
-  ASSERT_TRUE(object_class != NULL);
+  ASSERT_NE(object_class, nullptr);
   jclass string_class = env_->FindClass("java/lang/String");
-  ASSERT_TRUE(string_class != NULL);
+  ASSERT_NE(string_class, nullptr);
 
   ASSERT_TRUE(env_->IsAssignableFrom(object_class, string_class));
   ASSERT_FALSE(env_->IsAssignableFrom(string_class, object_class));
+
+  // Null as either class should fail.
+  CheckJniAbortCatcher jni_abort_catcher;
+  EXPECT_EQ(env_->IsAssignableFrom(nullptr, string_class), JNI_FALSE);
+  jni_abort_catcher.Check("java_class1 == null");
+  EXPECT_EQ(env_->IsAssignableFrom(object_class, nullptr), JNI_FALSE);
+  jni_abort_catcher.Check("java_class2 == null");
 }
 
 TEST_F(JniInternalTest, GetObjectRefType) {
   jclass local = env_->FindClass("java/lang/Object");
-  ASSERT_TRUE(local != NULL);
+  ASSERT_TRUE(local != nullptr);
   EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(local));
 
   jobject global = env_->NewGlobalRef(local);
@@ -604,33 +921,38 @@
   EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(invalid));
 
   // TODO: invoke a native method and test that its arguments are considered local references.
+
+  // Null as object should fail.
+  CheckJniAbortCatcher jni_abort_catcher;
+  EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(nullptr));
+  jni_abort_catcher.Check("java_object == null");
 }
 
 TEST_F(JniInternalTest, StaleWeakGlobal) {
   jclass java_lang_Class = env_->FindClass("java/lang/Class");
-  ASSERT_TRUE(java_lang_Class != NULL);
-  jobjectArray local_ref = env_->NewObjectArray(1, java_lang_Class, NULL);
-  ASSERT_TRUE(local_ref != NULL);
+  ASSERT_NE(java_lang_Class, nullptr);
+  jobjectArray local_ref = env_->NewObjectArray(1, java_lang_Class, nullptr);
+  ASSERT_NE(local_ref, nullptr);
   jweak weak_global = env_->NewWeakGlobalRef(local_ref);
-  ASSERT_TRUE(weak_global != NULL);
+  ASSERT_NE(weak_global, nullptr);
   env_->DeleteLocalRef(local_ref);
   Runtime::Current()->GetHeap()->CollectGarbage(false);  // GC should clear the weak global.
   jobject new_global_ref = env_->NewGlobalRef(weak_global);
-  EXPECT_TRUE(new_global_ref == NULL);
+  EXPECT_EQ(new_global_ref, nullptr);
   jobject new_local_ref = env_->NewLocalRef(weak_global);
-  EXPECT_TRUE(new_local_ref == NULL);
+  EXPECT_EQ(new_local_ref, nullptr);
 }
 
 TEST_F(JniInternalTest, NewStringUTF) {
-  EXPECT_TRUE(env_->NewStringUTF(NULL) == NULL);
+  EXPECT_EQ(env_->NewStringUTF(nullptr), nullptr);
   jstring s;
 
   s = env_->NewStringUTF("");
-  EXPECT_TRUE(s != NULL);
+  EXPECT_NE(s, nullptr);
   EXPECT_EQ(0, env_->GetStringLength(s));
   EXPECT_EQ(0, env_->GetStringUTFLength(s));
   s = env_->NewStringUTF("hello");
-  EXPECT_TRUE(s != NULL);
+  EXPECT_NE(s, nullptr);
   EXPECT_EQ(5, env_->GetStringLength(s));
   EXPECT_EQ(5, env_->GetStringUTFLength(s));
 
@@ -641,11 +963,11 @@
   jchar chars[] = { 'h', 'i' };
   jstring s;
   s = env_->NewString(chars, 0);
-  EXPECT_TRUE(s != NULL);
+  EXPECT_NE(s, nullptr);
   EXPECT_EQ(0, env_->GetStringLength(s));
   EXPECT_EQ(0, env_->GetStringUTFLength(s));
   s = env_->NewString(chars, 2);
-  EXPECT_TRUE(s != NULL);
+  EXPECT_NE(s, nullptr);
   EXPECT_EQ(2, env_->GetStringLength(s));
   EXPECT_EQ(2, env_->GetStringUTFLength(s));
 
@@ -654,7 +976,7 @@
 
 TEST_F(JniInternalTest, NewStringNullCharsZeroLength) {
   jstring s = env_->NewString(nullptr, 0);
-  EXPECT_TRUE(s != nullptr);
+  EXPECT_NE(s, nullptr);
   EXPECT_EQ(0, env_->GetStringLength(s));
 }
 
@@ -678,16 +1000,16 @@
 
 TEST_F(JniInternalTest, GetStringRegion_GetStringUTFRegion) {
   jstring s = env_->NewStringUTF("hello");
-  ASSERT_TRUE(s != NULL);
+  ASSERT_TRUE(s != nullptr);
 
-  env_->GetStringRegion(s, -1, 0, NULL);
-  EXPECT_EXCEPTION(sioobe_);
-  env_->GetStringRegion(s, 0, -1, NULL);
-  EXPECT_EXCEPTION(sioobe_);
-  env_->GetStringRegion(s, 0, 10, NULL);
-  EXPECT_EXCEPTION(sioobe_);
-  env_->GetStringRegion(s, 10, 1, NULL);
-  EXPECT_EXCEPTION(sioobe_);
+  env_->GetStringRegion(s, -1, 0, nullptr);
+  ExpectException(sioobe_);
+  env_->GetStringRegion(s, 0, -1, nullptr);
+  ExpectException(sioobe_);
+  env_->GetStringRegion(s, 0, 10, nullptr);
+  ExpectException(sioobe_);
+  env_->GetStringRegion(s, 10, 1, nullptr);
+  ExpectException(sioobe_);
 
   jchar chars[4] = { 'x', 'x', 'x', 'x' };
   env_->GetStringRegion(s, 1, 2, &chars[1]);
@@ -696,20 +1018,20 @@
   EXPECT_EQ('l', chars[2]);
   EXPECT_EQ('x', chars[3]);
 
-  // It's okay for the buffer to be NULL as long as the length is 0.
-  env_->GetStringRegion(s, 2, 0, NULL);
+  // It's okay for the buffer to be nullptr as long as the length is 0.
+  env_->GetStringRegion(s, 2, 0, nullptr);
   // Even if the offset is invalid...
-  env_->GetStringRegion(s, 123, 0, NULL);
-  EXPECT_EXCEPTION(sioobe_);
+  env_->GetStringRegion(s, 123, 0, nullptr);
+  ExpectException(sioobe_);
 
-  env_->GetStringUTFRegion(s, -1, 0, NULL);
-  EXPECT_EXCEPTION(sioobe_);
-  env_->GetStringUTFRegion(s, 0, -1, NULL);
-  EXPECT_EXCEPTION(sioobe_);
-  env_->GetStringUTFRegion(s, 0, 10, NULL);
-  EXPECT_EXCEPTION(sioobe_);
-  env_->GetStringUTFRegion(s, 10, 1, NULL);
-  EXPECT_EXCEPTION(sioobe_);
+  env_->GetStringUTFRegion(s, -1, 0, nullptr);
+  ExpectException(sioobe_);
+  env_->GetStringUTFRegion(s, 0, -1, nullptr);
+  ExpectException(sioobe_);
+  env_->GetStringUTFRegion(s, 0, 10, nullptr);
+  ExpectException(sioobe_);
+  env_->GetStringUTFRegion(s, 10, 1, nullptr);
+  ExpectException(sioobe_);
 
   char bytes[4] = { 'x', 'x', 'x', 'x' };
   env_->GetStringUTFRegion(s, 1, 2, &bytes[1]);
@@ -718,25 +1040,25 @@
   EXPECT_EQ('l', bytes[2]);
   EXPECT_EQ('x', bytes[3]);
 
-  // It's okay for the buffer to be NULL as long as the length is 0.
-  env_->GetStringUTFRegion(s, 2, 0, NULL);
+  // It's okay for the buffer to be nullptr as long as the length is 0.
+  env_->GetStringUTFRegion(s, 2, 0, nullptr);
   // Even if the offset is invalid...
-  env_->GetStringUTFRegion(s, 123, 0, NULL);
-  EXPECT_EXCEPTION(sioobe_);
+  env_->GetStringUTFRegion(s, 123, 0, nullptr);
+  ExpectException(sioobe_);
 }
 
 TEST_F(JniInternalTest, GetStringUTFChars_ReleaseStringUTFChars) {
-  // Passing in a NULL jstring is ignored normally, but caught by -Xcheck:jni.
+  // Passing in a nullptr jstring is ignored normally, but caught by -Xcheck:jni.
   {
     CheckJniAbortCatcher check_jni_abort_catcher;
-    EXPECT_TRUE(env_->GetStringUTFChars(NULL, NULL) == NULL);
+    EXPECT_EQ(env_->GetStringUTFChars(nullptr, nullptr), nullptr);
     check_jni_abort_catcher.Check("GetStringUTFChars received null jstring");
   }
 
   jstring s = env_->NewStringUTF("hello");
-  ASSERT_TRUE(s != NULL);
+  ASSERT_TRUE(s != nullptr);
 
-  const char* utf = env_->GetStringUTFChars(s, NULL);
+  const char* utf = env_->GetStringUTFChars(s, nullptr);
   EXPECT_STREQ("hello", utf);
   env_->ReleaseStringUTFChars(s, utf);
 
@@ -749,10 +1071,10 @@
 
 TEST_F(JniInternalTest, GetStringChars_ReleaseStringChars) {
   jstring s = env_->NewStringUTF("hello");
-  ASSERT_TRUE(s != NULL);
+  ASSERT_TRUE(s != nullptr);
 
   jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
-  const jchar* chars = env_->GetStringChars(s, NULL);
+  const jchar* chars = env_->GetStringChars(s, nullptr);
   EXPECT_EQ(expected[0], chars[0]);
   EXPECT_EQ(expected[1], chars[1]);
   EXPECT_EQ(expected[2], chars[2]);
@@ -773,10 +1095,10 @@
 
 TEST_F(JniInternalTest, GetStringCritical_ReleaseStringCritical) {
   jstring s = env_->NewStringUTF("hello");
-  ASSERT_TRUE(s != NULL);
+  ASSERT_TRUE(s != nullptr);
 
   jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
-  const jchar* chars = env_->GetStringCritical(s, NULL);
+  const jchar* chars = env_->GetStringCritical(s, nullptr);
   EXPECT_EQ(expected[0], chars[0]);
   EXPECT_EQ(expected[1], chars[1]);
   EXPECT_EQ(expected[2], chars[2]);
@@ -798,45 +1120,72 @@
 
 TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) {
   jclass java_lang_Class = env_->FindClass("java/lang/Class");
-  ASSERT_TRUE(java_lang_Class != NULL);
+  ASSERT_TRUE(java_lang_Class != nullptr);
 
-  jobjectArray array = env_->NewObjectArray(1, java_lang_Class, NULL);
-  EXPECT_TRUE(array != NULL);
-  EXPECT_TRUE(env_->GetObjectArrayElement(array, 0) == NULL);
+  jobjectArray array = env_->NewObjectArray(1, java_lang_Class, nullptr);
+  EXPECT_NE(array, nullptr);
+  EXPECT_EQ(env_->GetObjectArrayElement(array, 0), nullptr);
   env_->SetObjectArrayElement(array, 0, java_lang_Class);
   EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(array, 0), java_lang_Class));
 
   // ArrayIndexOutOfBounds for negative index.
   env_->SetObjectArrayElement(array, -1, java_lang_Class);
-  EXPECT_EXCEPTION(aioobe_);
+  ExpectException(aioobe_);
 
   // ArrayIndexOutOfBounds for too-large index.
   env_->SetObjectArrayElement(array, 1, java_lang_Class);
-  EXPECT_EXCEPTION(aioobe_);
+  ExpectException(aioobe_);
 
   // ArrayStoreException thrown for bad types.
   env_->SetObjectArrayElement(array, 0, env_->NewStringUTF("not a jclass!"));
-  EXPECT_EXCEPTION(ase_);
+  ExpectException(ase_);
+
+  // Null as array should fail.
+  CheckJniAbortCatcher jni_abort_catcher;
+  EXPECT_EQ(nullptr, env_->GetObjectArrayElement(nullptr, 0));
+  jni_abort_catcher.Check("java_array == null");
+  env_->SetObjectArrayElement(nullptr, 0, nullptr);
+  jni_abort_catcher.Check("java_array == null");
 }
 
 #define EXPECT_STATIC_PRIMITIVE_FIELD(type, field_name, sig, value1, value2) \
   do { \
     jfieldID fid = env_->GetStaticFieldID(c, field_name, sig); \
-    EXPECT_TRUE(fid != NULL); \
+    EXPECT_NE(fid, nullptr); \
     env_->SetStatic ## type ## Field(c, fid, value1); \
-    EXPECT_TRUE(value1 == env_->GetStatic ## type ## Field(c, fid)); \
+    EXPECT_EQ(value1, env_->GetStatic ## type ## Field(c, fid)); \
     env_->SetStatic ## type ## Field(c, fid, value2); \
-    EXPECT_TRUE(value2 == env_->GetStatic ## type ## Field(c, fid)); \
+    EXPECT_EQ(value2, env_->GetStatic ## type ## Field(c, fid)); \
+    \
+    CheckJniAbortCatcher jni_abort_catcher; \
+    env_->GetStatic ## type ## Field(nullptr, fid); \
+    jni_abort_catcher.Check("received null jclass"); \
+    env_->SetStatic ## type ## Field(nullptr, fid, value1); \
+    jni_abort_catcher.Check("received null jclass"); \
+    env_->GetStatic ## type ## Field(c, nullptr); \
+    jni_abort_catcher.Check("fid == null"); \
+    env_->SetStatic ## type ## Field(c, nullptr, value1); \
+    jni_abort_catcher.Check("fid == null"); \
   } while (false)
 
 #define EXPECT_PRIMITIVE_FIELD(instance, type, field_name, sig, value1, value2) \
   do { \
     jfieldID fid = env_->GetFieldID(c, field_name, sig); \
-    EXPECT_TRUE(fid != NULL); \
+    EXPECT_NE(fid, nullptr); \
     env_->Set ## type ## Field(instance, fid, value1); \
-    EXPECT_TRUE(value1 == env_->Get ## type ## Field(instance, fid)); \
+    EXPECT_EQ(value1, env_->Get ## type ## Field(instance, fid)); \
     env_->Set ## type ## Field(instance, fid, value2); \
-    EXPECT_TRUE(value2 == env_->Get ## type ## Field(instance, fid)); \
+    EXPECT_EQ(value2, env_->Get ## type ## Field(instance, fid)); \
+    \
+    CheckJniAbortCatcher jni_abort_catcher; \
+    env_->Get ## type ## Field(nullptr, fid); \
+    jni_abort_catcher.Check("obj == null"); \
+    env_->Set ## type ## Field(nullptr, fid, value1); \
+    jni_abort_catcher.Check("obj == null"); \
+    env_->Get ## type ## Field(instance, nullptr); \
+    jni_abort_catcher.Check("fid == null"); \
+    env_->Set ## type ## Field(instance, nullptr, value1); \
+    jni_abort_catcher.Check("fid == null"); \
   } while (false)
 
 
@@ -845,14 +1194,14 @@
   Thread::Current()->TransitionFromSuspendedToRunnable();
   LoadDex("AllFields");
   bool started = runtime_->Start();
-  CHECK(started);
+  ASSERT_TRUE(started);
 
   jclass c = env_->FindClass("AllFields");
-  ASSERT_TRUE(c != NULL);
+  ASSERT_NE(c, nullptr);
   jobject o = env_->AllocObject(c);
-  ASSERT_TRUE(o != NULL);
+  ASSERT_NE(o, nullptr);
 
-  EXPECT_STATIC_PRIMITIVE_FIELD(Boolean, "sZ", "Z", true, false);
+  EXPECT_STATIC_PRIMITIVE_FIELD(Boolean, "sZ", "Z", JNI_TRUE, JNI_FALSE);
   EXPECT_STATIC_PRIMITIVE_FIELD(Byte, "sB", "B", 1, 2);
   EXPECT_STATIC_PRIMITIVE_FIELD(Char, "sC", "C", 'a', 'b');
   EXPECT_STATIC_PRIMITIVE_FIELD(Double, "sD", "D", 1.0, 2.0);
@@ -861,7 +1210,7 @@
   EXPECT_STATIC_PRIMITIVE_FIELD(Long, "sJ", "J", 1, 2);
   EXPECT_STATIC_PRIMITIVE_FIELD(Short, "sS", "S", 1, 2);
 
-  EXPECT_PRIMITIVE_FIELD(o, Boolean, "iZ", "Z", true, false);
+  EXPECT_PRIMITIVE_FIELD(o, Boolean, "iZ", "Z", JNI_TRUE, JNI_FALSE);
   EXPECT_PRIMITIVE_FIELD(o, Byte, "iB", "B", 1, 2);
   EXPECT_PRIMITIVE_FIELD(o, Char, "iC", "C", 'a', 'b');
   EXPECT_PRIMITIVE_FIELD(o, Double, "iD", "D", 1.0, 2.0);
@@ -878,19 +1227,19 @@
   runtime_->Start();
 
   jclass c = env_->FindClass("AllFields");
-  ASSERT_TRUE(c != NULL);
+  ASSERT_NE(c, nullptr);
   jobject o = env_->AllocObject(c);
-  ASSERT_TRUE(o != NULL);
+  ASSERT_NE(o, nullptr);
 
   jstring s1 = env_->NewStringUTF("hello");
-  ASSERT_TRUE(s1 != NULL);
+  ASSERT_NE(s1, nullptr);
   jstring s2 = env_->NewStringUTF("world");
-  ASSERT_TRUE(s2 != NULL);
+  ASSERT_NE(s2, nullptr);
 
   jfieldID s_fid = env_->GetStaticFieldID(c, "sObject", "Ljava/lang/Object;");
-  ASSERT_TRUE(s_fid != NULL);
+  ASSERT_NE(s_fid, nullptr);
   jfieldID i_fid = env_->GetFieldID(c, "iObject", "Ljava/lang/Object;");
-  ASSERT_TRUE(i_fid != NULL);
+  ASSERT_NE(i_fid, nullptr);
 
   env_->SetStaticObjectField(c, s_fid, s1);
   ASSERT_TRUE(env_->IsSameObject(s1, env_->GetStaticObjectField(c, s_fid)));
@@ -903,27 +1252,27 @@
   ASSERT_TRUE(env_->IsSameObject(s2, env_->GetObjectField(o, i_fid)));
 }
 
-TEST_F(JniInternalTest, NewLocalRef_NULL) {
-  EXPECT_TRUE(env_->NewLocalRef(NULL) == NULL);
+TEST_F(JniInternalTest, NewLocalRef_nullptr) {
+  EXPECT_EQ(env_->NewLocalRef(nullptr), nullptr);
 }
 
 TEST_F(JniInternalTest, NewLocalRef) {
   jstring s = env_->NewStringUTF("");
-  ASSERT_TRUE(s != NULL);
+  ASSERT_NE(s, nullptr);
   jobject o = env_->NewLocalRef(s);
-  EXPECT_TRUE(o != NULL);
-  EXPECT_TRUE(o != s);
+  EXPECT_NE(o, nullptr);
+  EXPECT_NE(o, s);
 
   EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(o));
 }
 
-TEST_F(JniInternalTest, DeleteLocalRef_NULL) {
-  env_->DeleteLocalRef(NULL);
+TEST_F(JniInternalTest, DeleteLocalRef_nullptr) {
+  env_->DeleteLocalRef(nullptr);
 }
 
 TEST_F(JniInternalTest, DeleteLocalRef) {
   jstring s = env_->NewStringUTF("");
-  ASSERT_TRUE(s != NULL);
+  ASSERT_NE(s, nullptr);
   env_->DeleteLocalRef(s);
 
   // Currently, deleting an already-deleted reference is just a CheckJNI warning.
@@ -937,9 +1286,9 @@
   }
 
   s = env_->NewStringUTF("");
-  ASSERT_TRUE(s != NULL);
+  ASSERT_NE(s, nullptr);
   jobject o = env_->NewLocalRef(s);
-  ASSERT_TRUE(o != NULL);
+  ASSERT_NE(o, nullptr);
 
   env_->DeleteLocalRef(s);
   env_->DeleteLocalRef(o);
@@ -951,7 +1300,7 @@
   // Android historically treated it, and it's how the RI treats it. It's also the more useful
   // interpretation!
   ASSERT_EQ(JNI_OK, env_->PushLocalFrame(0));
-  env_->PopLocalFrame(NULL);
+  env_->PopLocalFrame(nullptr);
 
   // Negative capacities are not allowed.
   ASSERT_EQ(JNI_ERR, env_->PushLocalFrame(-1));
@@ -962,7 +1311,7 @@
 
 TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) {
   jobject original = env_->NewStringUTF("");
-  ASSERT_TRUE(original != NULL);
+  ASSERT_NE(original, nullptr);
 
   jobject outer;
   jobject inner1, inner2;
@@ -988,7 +1337,7 @@
     // gets a new local reference...
     EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
 
-    env_->PopLocalFrame(NULL);
+    env_->PopLocalFrame(nullptr);
   }
   EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
   EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(outer));
@@ -996,30 +1345,30 @@
   EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
 }
 
-TEST_F(JniInternalTest, NewGlobalRef_NULL) {
-  EXPECT_TRUE(env_->NewGlobalRef(NULL) == NULL);
+TEST_F(JniInternalTest, NewGlobalRef_nullptr) {
+  EXPECT_EQ(env_->NewGlobalRef(nullptr), nullptr);
 }
 
 TEST_F(JniInternalTest, NewGlobalRef) {
   jstring s = env_->NewStringUTF("");
-  ASSERT_TRUE(s != NULL);
+  ASSERT_NE(s, nullptr);
   jobject o = env_->NewGlobalRef(s);
-  EXPECT_TRUE(o != NULL);
-  EXPECT_TRUE(o != s);
+  EXPECT_NE(o, nullptr);
+  EXPECT_NE(o, s);
 
-  // TODO: check that o is a global reference.
+  EXPECT_EQ(env_->GetObjectRefType(o), JNIGlobalRefType);
 }
 
-TEST_F(JniInternalTest, DeleteGlobalRef_NULL) {
-  env_->DeleteGlobalRef(NULL);
+TEST_F(JniInternalTest, DeleteGlobalRef_nullptr) {
+  env_->DeleteGlobalRef(nullptr);
 }
 
 TEST_F(JniInternalTest, DeleteGlobalRef) {
   jstring s = env_->NewStringUTF("");
-  ASSERT_TRUE(s != NULL);
+  ASSERT_NE(s, nullptr);
 
   jobject o = env_->NewGlobalRef(s);
-  ASSERT_TRUE(o != NULL);
+  ASSERT_NE(o, nullptr);
   env_->DeleteGlobalRef(o);
 
   // Currently, deleting an already-deleted reference is just a CheckJNI warning.
@@ -1033,38 +1382,38 @@
   }
 
   jobject o1 = env_->NewGlobalRef(s);
-  ASSERT_TRUE(o1 != NULL);
+  ASSERT_NE(o1, nullptr);
   jobject o2 = env_->NewGlobalRef(s);
-  ASSERT_TRUE(o2 != NULL);
+  ASSERT_NE(o2, nullptr);
 
   env_->DeleteGlobalRef(o1);
   env_->DeleteGlobalRef(o2);
 }
 
-TEST_F(JniInternalTest, NewWeakGlobalRef_NULL) {
-  EXPECT_TRUE(env_->NewWeakGlobalRef(NULL) == NULL);
+TEST_F(JniInternalTest, NewWeakGlobalRef_nullptr) {
+  EXPECT_EQ(env_->NewWeakGlobalRef(nullptr),   nullptr);
 }
 
 TEST_F(JniInternalTest, NewWeakGlobalRef) {
   jstring s = env_->NewStringUTF("");
-  ASSERT_TRUE(s != NULL);
+  ASSERT_NE(s, nullptr);
   jobject o = env_->NewWeakGlobalRef(s);
-  EXPECT_TRUE(o != NULL);
-  EXPECT_TRUE(o != s);
+  EXPECT_NE(o, nullptr);
+  EXPECT_NE(o, s);
 
-  // TODO: check that o is a weak global reference.
+  EXPECT_EQ(env_->GetObjectRefType(o), JNIWeakGlobalRefType);
 }
 
-TEST_F(JniInternalTest, DeleteWeakGlobalRef_NULL) {
-  env_->DeleteWeakGlobalRef(NULL);
+TEST_F(JniInternalTest, DeleteWeakGlobalRef_nullptr) {
+  env_->DeleteWeakGlobalRef(nullptr);
 }
 
 TEST_F(JniInternalTest, DeleteWeakGlobalRef) {
   jstring s = env_->NewStringUTF("");
-  ASSERT_TRUE(s != NULL);
+  ASSERT_NE(s, nullptr);
 
   jobject o = env_->NewWeakGlobalRef(s);
-  ASSERT_TRUE(o != NULL);
+  ASSERT_NE(o, nullptr);
   env_->DeleteWeakGlobalRef(o);
 
   // Currently, deleting an already-deleted reference is just a CheckJNI warning.
@@ -1078,21 +1427,21 @@
   }
 
   jobject o1 = env_->NewWeakGlobalRef(s);
-  ASSERT_TRUE(o1 != NULL);
+  ASSERT_NE(o1, nullptr);
   jobject o2 = env_->NewWeakGlobalRef(s);
-  ASSERT_TRUE(o2 != NULL);
+  ASSERT_NE(o2, nullptr);
 
   env_->DeleteWeakGlobalRef(o1);
   env_->DeleteWeakGlobalRef(o2);
 }
 
 TEST_F(JniInternalTest, Throw) {
-  EXPECT_EQ(JNI_ERR, env_->Throw(NULL));
+  EXPECT_EQ(JNI_ERR, env_->Throw(nullptr));
 
   jclass exception_class = env_->FindClass("java/lang/RuntimeException");
-  ASSERT_TRUE(exception_class != NULL);
+  ASSERT_TRUE(exception_class != nullptr);
   jthrowable exception = reinterpret_cast<jthrowable>(env_->AllocObject(exception_class));
-  ASSERT_TRUE(exception != NULL);
+  ASSERT_TRUE(exception != nullptr);
 
   EXPECT_EQ(JNI_OK, env_->Throw(exception));
   EXPECT_TRUE(env_->ExceptionCheck());
@@ -1102,10 +1451,10 @@
 }
 
 TEST_F(JniInternalTest, ThrowNew) {
-  EXPECT_EQ(JNI_ERR, env_->Throw(NULL));
+  EXPECT_EQ(JNI_ERR, env_->Throw(nullptr));
 
   jclass exception_class = env_->FindClass("java/lang/RuntimeException");
-  ASSERT_TRUE(exception_class != NULL);
+  ASSERT_TRUE(exception_class != nullptr);
 
   jthrowable thrown_exception;
 
@@ -1115,7 +1464,7 @@
   env_->ExceptionClear();
   EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
 
-  EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, NULL));
+  EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, nullptr));
   EXPECT_TRUE(env_->ExceptionCheck());
   thrown_exception = env_->ExceptionOccurred();
   env_->ExceptionClear();
@@ -1141,26 +1490,26 @@
   ASSERT_TRUE(started);
 
   jclass buffer_class = env_->FindClass("java/nio/Buffer");
-  ASSERT_TRUE(buffer_class != NULL);
+  ASSERT_NE(buffer_class, nullptr);
 
   char bytes[1024];
   jobject buffer = env_->NewDirectByteBuffer(bytes, sizeof(bytes));
-  ASSERT_TRUE(buffer != NULL);
+  ASSERT_NE(buffer, nullptr);
   ASSERT_TRUE(env_->IsInstanceOf(buffer, buffer_class));
-  ASSERT_TRUE(env_->GetDirectBufferAddress(buffer) == bytes);
-  ASSERT_TRUE(env_->GetDirectBufferCapacity(buffer) == sizeof(bytes));
+  ASSERT_EQ(env_->GetDirectBufferAddress(buffer), bytes);
+  ASSERT_EQ(env_->GetDirectBufferCapacity(buffer), static_cast<jlong>(sizeof(bytes)));
 }
 
 TEST_F(JniInternalTest, MonitorEnterExit) {
-  // Create an object to torture
+  // Create an object to torture.
   jclass object_class = env_->FindClass("java/lang/Object");
-  ASSERT_TRUE(object_class != NULL);
+  ASSERT_NE(object_class, nullptr);
   jobject object = env_->AllocObject(object_class);
-  ASSERT_TRUE(object != NULL);
+  ASSERT_NE(object, nullptr);
 
   // Expected class of exceptions
   jclass imse_class = env_->FindClass("java/lang/IllegalMonitorStateException");
-  ASSERT_TRUE(imse_class != NULL);
+  ASSERT_NE(imse_class, nullptr);
 
   jthrowable thrown_exception;
 
@@ -1197,13 +1546,13 @@
   env_->ExceptionClear();
   EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
 
-  // It's an error to call MonitorEnter or MonitorExit on NULL.
+  // It's an error to call MonitorEnter or MonitorExit on nullptr.
   {
     CheckJniAbortCatcher check_jni_abort_catcher;
-    env_->MonitorEnter(NULL);
+    env_->MonitorEnter(nullptr);
     check_jni_abort_catcher.Check("in call to MonitorEnter");
 
-    env_->MonitorExit(NULL);
+    env_->MonitorExit(nullptr);
     check_jni_abort_catcher.Check("in call to MonitorExit");
   }
 }
@@ -1215,7 +1564,7 @@
 
   jint err = vm_->DetachCurrentThread();
   EXPECT_EQ(JNI_ERR, err);
-  vm_->AttachCurrentThread(&env_, NULL);  // need attached thread for CommonRuntimeTest::TearDown
+  vm_->AttachCurrentThread(&env_, nullptr);  // need attached thread for CommonRuntimeTest::TearDown
 }
 
 }  // namespace art
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 238506e..1b8106e 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -155,14 +155,19 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static void SetArrayClass(Class* array_class) {
-    CHECK(array_class_ == NULL);
-    CHECK(array_class != NULL);
+    CHECK(array_class_ == nullptr);
+    CHECK(array_class != nullptr);
     array_class_ = array_class;
   }
 
+  static Class* GetArrayClass() {
+    DCHECK(array_class_ != nullptr);
+    return array_class_;
+  }
+
   static void ResetArrayClass() {
-    CHECK(array_class_ != NULL);
-    array_class_ = NULL;
+    CHECK(array_class_ != nullptr);
+    array_class_ = nullptr;
   }
 
   static void VisitRoots(RootCallback* callback, void* arg)
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 50a8e47..8d183da 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -66,10 +66,6 @@
     ThrowNullPointerException(NULL, "element class == null");
     return nullptr;
   }
-  if (UNLIKELY(element_class->IsPrimitiveVoid())) {
-    ThrowIllegalArgumentException(NULL, "Can't allocate an array of void");
-    return nullptr;
-  }
   Runtime* runtime = Runtime::Current();
   mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), element_class);
   if (UNLIKELY(array_class == nullptr)) {
@@ -93,10 +89,6 @@
     ThrowNullPointerException(NULL, "element class == null");
     return nullptr;
   }
-  if (UNLIKELY(element_class->IsPrimitiveVoid())) {
-    ThrowIllegalArgumentException(NULL, "Can't allocate an array of void");
-    return nullptr;
-  }
   Runtime* runtime = Runtime::Current();
   mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), element_class);
   if (UNLIKELY(array_class == nullptr)) {
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index 623b0c6..55b6a27 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -689,9 +689,7 @@
 
   if (compiler_callbacks_ == nullptr && image_.empty()) {
     image_ += GetAndroidRoot();
-    image_ += "/framework/boot-";
-    image_ += GetInstructionSetString(image_isa_);
-    image_ += ".art";
+    image_ += "/framework/boot.art";
   }
   if (heap_growth_limit_ == 0) {
     heap_growth_limit_ = heap_maximum_size_;