diff options
-rw-r--r-- | src/class_linker.cc | 24 | ||||
-rw-r--r-- | src/dalvik_system_VMRuntime.cc | 2 | ||||
-rw-r--r-- | src/java_lang_Class.cc | 25 | ||||
-rw-r--r-- | src/java_lang_System.cc | 9 | ||||
-rw-r--r-- | src/java_lang_reflect_Constructor.cc | 2 | ||||
-rw-r--r-- | src/java_lang_reflect_Field.cc | 4 | ||||
-rw-r--r-- | src/jni_internal.cc | 16 | ||||
-rw-r--r-- | src/jni_internal_test.cc | 10 | ||||
-rw-r--r-- | src/monitor.cc | 6 | ||||
-rw-r--r-- | src/object.cc | 6 | ||||
-rw-r--r-- | src/reflection.cc | 6 | ||||
-rw-r--r-- | src/runtime_support.cc | 54 | ||||
-rw-r--r-- | src/thread.cc | 7 | ||||
-rw-r--r-- | src/thread.h | 5 | ||||
-rw-r--r-- | test/034-call-null/expected.txt | 1 | ||||
-rw-r--r-- | test/038-inner-null/expected.txt | 1 | ||||
-rw-r--r-- | test/054-uncaught/expected.txt | 1 |
17 files changed, 93 insertions, 86 deletions
diff --git a/src/class_linker.cc b/src/class_linker.cc index 1963985..eade908 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -61,7 +61,7 @@ void ThrowNoSuchMethodError(const char* kind, if (dex_cache) { msg << " (defined in " << dex_cache->GetLocation()->ToModifiedUtf8() << ")"; } - Thread::Current()->ThrowNewException("Ljava/lang/NoSuchMethodError;", "%s", msg.str().c_str()); + Thread::Current()->ThrowNewException("Ljava/lang/NoSuchMethodError;", msg.str().c_str()); } void ThrowEarlierClassFailure(Class* c) { @@ -76,7 +76,7 @@ void ThrowEarlierClassFailure(Class* c) { if (c->GetVerifyErrorClass() != NULL) { // TODO: change the verifier to store an _instance_, with a useful detail message? std::string error_descriptor(c->GetVerifyErrorClass()->GetDescriptor()->ToModifiedUtf8()); - Thread::Current()->ThrowNewException(error_descriptor.c_str(), "%s", + Thread::Current()->ThrowNewException(error_descriptor.c_str(), PrettyDescriptor(c->GetDescriptor()).c_str()); } else { ThrowNoClassDefFoundError("%s", PrettyDescriptor(c->GetDescriptor()).c_str()); @@ -816,7 +816,7 @@ Class* ClassLinker::FindClass(const StringPiece& descriptor, ObjectLock lock(klass); // Check for circular dependencies between classes. if (!klass->IsResolved() && klass->GetClinitThreadId() == self->GetTid()) { - self->ThrowNewException("Ljava/lang/ClassCircularityError;", "%s", + self->ThrowNewException("Ljava/lang/ClassCircularityError;", PrettyDescriptor(klass->GetDescriptor()).c_str()); return NULL; } @@ -1416,7 +1416,7 @@ bool ClassLinker::WaitForInitializeClass(Class* klass, Thread* self, ObjectLock& // "interruptShouldThrow" was set), bail out. if (self->IsExceptionPending()) { // TODO: set cause of ExceptionInInitializerError to self->GetException() - self->ThrowNewException("Ljava/lang/ExceptionInInitializerError;", + self->ThrowNewExceptionF("Ljava/lang/ExceptionInInitializerError;", "Exception %s thrown while initializing class %s", PrettyTypeOf(self->GetException()).c_str(), PrettyDescriptor(klass->GetDescriptor()).c_str()); @@ -1430,7 +1430,7 @@ bool ClassLinker::WaitForInitializeClass(Class* klass, Thread* self, ObjectLock& if (klass->IsErroneous()) { // The caller wants an exception, but it was thrown in a // different thread. Synthesize one here. - self->ThrowNewException("Ljava/lang/NoClassDefFoundError;", + self->ThrowNewExceptionF("Ljava/lang/NoClassDefFoundError;", "<clinit> failed for class %s; see exception in other thread", PrettyDescriptor(klass->GetDescriptor()).c_str()); return false; @@ -1722,7 +1722,7 @@ bool ClassLinker::LoadSuperAndInterfaces(Class* klass, const DexFile& dex_file) // Verify if (!klass->CanAccess(interface)) { // TODO: the RI seemed to ignore this in my testing. - Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessError;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;", "Interface %s implemented by class %s is inaccessible", PrettyDescriptor(interface->GetDescriptor()).c_str(), PrettyDescriptor(klass->GetDescriptor()).c_str()); @@ -1739,7 +1739,7 @@ bool ClassLinker::LinkSuperClass(Class* klass) { Class* super = klass->GetSuperClass(); if (klass->GetDescriptor()->Equals("Ljava/lang/Object;")) { if (super != NULL) { - Thread::Current()->ThrowNewException("Ljava/lang/ClassFormatError;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassFormatError;", "java.lang.Object must not have a superclass"); return false; } @@ -1753,7 +1753,7 @@ bool ClassLinker::LinkSuperClass(Class* klass) { } // Verify if (super->IsFinal() || super->IsInterface()) { - Thread::Current()->ThrowNewException("Ljava/lang/IncompatibleClassChangeError;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;", "Superclass %s of %s is %s", PrettyDescriptor(super->GetDescriptor()).c_str(), PrettyDescriptor(klass->GetDescriptor()).c_str(), @@ -1761,7 +1761,7 @@ bool ClassLinker::LinkSuperClass(Class* klass) { return false; } if (!klass->CanAccess(super)) { - Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessError;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;", "Superclass %s is inaccessible by %s", PrettyDescriptor(super->GetDescriptor()).c_str(), PrettyDescriptor(klass->GetDescriptor()).c_str()); @@ -1894,7 +1894,7 @@ bool ClassLinker::LinkInterfaceMethods(Class* klass) { Class* interface = klass->GetInterface(i); DCHECK(interface != NULL); if (!interface->IsInterface()) { - Thread::Current()->ThrowNewException("Ljava/lang/IncompatibleClassChangeError;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;", "Class %s implements non-interface class %s", PrettyDescriptor(klass->GetDescriptor()).c_str(), PrettyDescriptor(interface->GetDescriptor()).c_str()); @@ -1936,7 +1936,7 @@ bool ClassLinker::LinkInterfaceMethods(Class* klass) { Method* vtable_method = vtable->Get(k); if (interface_method->HasSameNameAndDescriptor(vtable_method)) { if (!vtable_method->IsPublic()) { - Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessError;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;", "Implementation not public: %s", PrettyMethod(vtable_method).c_str()); return false; } @@ -2250,7 +2250,7 @@ Class* ClassLinker::ResolveType(const DexFile& dex_file, Class* check = resolved->IsArrayClass() ? resolved->GetComponentType() : resolved; if (dex_cache != check->GetDexCache()) { if (check->GetClassLoader() != NULL) { - Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessError;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;", "Class with type index %d resolved by unexpected .dex", type_idx); resolved = NULL; } diff --git a/src/dalvik_system_VMRuntime.cc b/src/dalvik_system_VMRuntime.cc index 1bc1e39..8d4aa8b 100644 --- a/src/dalvik_system_VMRuntime.cc +++ b/src/dalvik_system_VMRuntime.cc @@ -56,7 +56,7 @@ jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaElementCla return NULL; } if (length < 0) { - Thread::Current()->ThrowNewException("Ljava/lang/NegativeArraySizeException;", "%d", length); + Thread::Current()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", length); return NULL; } diff --git a/src/java_lang_Class.cc b/src/java_lang_Class.cc index de5315a..a404523 100644 --- a/src/java_lang_Class.cc +++ b/src/java_lang_Class.cc @@ -38,7 +38,7 @@ jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean initia // is especially handy for array types, since we want to avoid // auto-generating bogus array classes. if (!IsValidClassName(name.c_str(), true, true)) { - Thread::Current()->ThrowNewException("Ljava/lang/ClassNotFoundException;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassNotFoundException;", "Invalid name: %s", name.c_str()); return NULL; } @@ -53,8 +53,7 @@ jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean initia // TODO: chain exceptions? DCHECK(env->ExceptionCheck()); env->ExceptionClear(); - Thread::Current()->ThrowNewException("Ljava/lang/ClassNotFoundException;", - "%s", name.c_str()); + Thread::Current()->ThrowNewException("Ljava/lang/ClassNotFoundException;", name.c_str()); return NULL; } if (initialize) { @@ -373,7 +372,7 @@ bool CheckMemberAccess(const Class* access_from, const Class* access_to, uint32_ jobject Class_newInstanceImpl(JNIEnv* env, jobject javaThis) { Class* c = Decode<Class*>(env, javaThis); if (c->IsPrimitive() || c->IsInterface() || c->IsArrayClass() || c->IsAbstract()) { - Thread::Current()->ThrowNewException("Ljava/lang/InstantiationException;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/InstantiationException;", "Class %s can not be instantiated", PrettyDescriptor(c->GetDescriptor()).c_str()); return NULL; } @@ -384,7 +383,7 @@ jobject Class_newInstanceImpl(JNIEnv* env, jobject javaThis) { Method* init = c->FindDirectMethod("<init>", "()V"); if (init == NULL) { - Thread::Current()->ThrowNewException("Ljava/lang/InstantiationException;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/InstantiationException;", "Class %s has no default <init>()V constructor", PrettyDescriptor(c->GetDescriptor()).c_str()); return NULL; } @@ -405,17 +404,17 @@ jobject Class_newInstanceImpl(JNIEnv* env, jobject javaThis) { Class* caller_class = caller_caller->GetDeclaringClass(); if (!caller_class->CanAccess(c)) { - Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessException;", - "Class %s is not accessible from class %s", - PrettyDescriptor(c->GetDescriptor()).c_str(), - PrettyDescriptor(caller_class->GetDescriptor()).c_str()); + Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessException;", + "Class %s is not accessible from class %s", + PrettyDescriptor(c->GetDescriptor()).c_str(), + PrettyDescriptor(caller_class->GetDescriptor()).c_str()); return NULL; } if (!CheckMemberAccess(caller_class, init->GetDeclaringClass(), init->GetAccessFlags())) { - Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessException;", - "%s is not accessible from class %s", - PrettyMethod(init).c_str(), - PrettyDescriptor(caller_class->GetDescriptor()).c_str()); + Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessException;", + "%s is not accessible from class %s", + PrettyMethod(init).c_str(), + PrettyDescriptor(caller_class->GetDescriptor()).c_str()); return NULL; } diff --git a/src/java_lang_System.cc b/src/java_lang_System.cc index 42bae22..4a6e8db 100644 --- a/src/java_lang_System.cc +++ b/src/java_lang_System.cc @@ -106,7 +106,8 @@ namespace { void ThrowArrayStoreException_NotAnArray(const char* identifier, Object* array) { std::string actualType(PrettyTypeOf(array)); - Thread::Current()->ThrowNewException("Ljava/lang/ArrayStoreException;", "%s is not an array: %s", identifier, actualType.c_str()); + Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;", + "%s is not an array: %s", identifier, actualType.c_str()); } void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst, jint dstPos, jint length) { @@ -140,7 +141,7 @@ void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject // Bounds checking. if (srcPos < 0 || dstPos < 0 || length < 0 || srcPos > srcArray->GetLength() - length || dstPos > dstArray->GetLength() - length) { - self->ThrowNewException("Ljava/lang/ArrayIndexOutOfBoundsException;", + self->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;", "src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d", srcArray->GetLength(), srcPos, dstArray->GetLength(), dstPos, length); return; @@ -155,7 +156,7 @@ void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject if (srcComponentType->IsPrimitive() != dstComponentType->IsPrimitive() || srcComponentType != dstComponentType) { std::string srcType(PrettyTypeOf(srcArray)); std::string dstType(PrettyTypeOf(dstArray)); - self->ThrowNewException("Ljava/lang/ArrayStoreException;", + self->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;", "Incompatible types: src=%s, dst=%s", srcType.c_str(), dstType.c_str()); return; } @@ -231,7 +232,7 @@ void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject if (copyCount != length) { std::string actualSrcType(PrettyTypeOf(srcObj[copyCount])); std::string dstType(PrettyTypeOf(dstArray)); - self->ThrowNewException("Ljava/lang/ArrayStoreException;", + self->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;", "source[%d] of type %s cannot be stored in destination array of type %s", srcPos + copyCount, actualSrcType.c_str(), dstType.c_str()); return; diff --git a/src/java_lang_reflect_Constructor.cc b/src/java_lang_reflect_Constructor.cc index 6cc8ea7..4d42450 100644 --- a/src/java_lang_reflect_Constructor.cc +++ b/src/java_lang_reflect_Constructor.cc @@ -35,7 +35,7 @@ namespace { jobject Constructor_constructNative(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs, jclass javaDeclaringClass, jobjectArray javaParams, jint, jboolean) { Class* c = Decode<Class*>(env, javaDeclaringClass); if (c->IsAbstract()) { - Thread::Current()->ThrowNewException("Ljava/lang/InstantiationException;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/InstantiationException;", "Can't instantiate abstract class %s", PrettyDescriptor(c->GetDescriptor()).c_str()); return NULL; } diff --git a/src/java_lang_reflect_Field.cc b/src/java_lang_reflect_Field.cc index 185fabc..8e09adb 100644 --- a/src/java_lang_reflect_Field.cc +++ b/src/java_lang_reflect_Field.cc @@ -66,7 +66,7 @@ bool GetFieldValue(Object* o, Field* f, JValue& value, bool allow_references) { // Never okay. break; } - Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;", "Not a primitive field: %s", PrettyField(f).c_str()); return false; } @@ -165,7 +165,7 @@ void SetFieldValue(Object* o, Field* f, const JValue& new_value, bool allow_refe // Else fall through to report an error. case Class::kPrimVoid: // Never okay. - Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;", "Not a primitive field: %s", PrettyField(f).c_str()); return; } diff --git a/src/jni_internal.cc b/src/jni_internal.cc index 144ec22..bc1de52 100644 --- a/src/jni_internal.cc +++ b/src/jni_internal.cc @@ -253,7 +253,7 @@ std::string NormalizeJniClassDescriptor(const char* name) { void ThrowNoSuchMethodError(ScopedJniThreadState& ts, Class* c, const char* name, const char* sig, const char* kind) { std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8()); - ts.Self()->ThrowNewException("Ljava/lang/NoSuchMethodError;", + ts.Self()->ThrowNewExceptionF("Ljava/lang/NoSuchMethodError;", "no %s method \"%s.%s%s\"", kind, class_descriptor.c_str(), name, sig); } @@ -306,7 +306,7 @@ jfieldID FindFieldID(ScopedJniThreadState& ts, jclass jni_class, const char* nam DCHECK(ts.Self()->IsExceptionPending()); ts.Self()->ClearException(); std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8()); - ts.Self()->ThrowNewException("Ljava/lang/NoSuchFieldError;", + ts.Self()->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;", "no type \"%s\" found and so no field \"%s\" could be found in class " "\"%s\" or its superclasses", sig, name, class_descriptor.c_str()); return NULL; @@ -318,7 +318,7 @@ jfieldID FindFieldID(ScopedJniThreadState& ts, jclass jni_class, const char* nam } if (field == NULL) { std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8()); - ts.Self()->ThrowNewException("Ljava/lang/NoSuchFieldError;", + ts.Self()->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;", "no \"%s\" field \"%s\" in class \"%s\" or its superclasses", sig, name, class_descriptor.c_str()); return NULL; @@ -366,12 +366,12 @@ void ReleasePrimitiveArray(ScopedJniThreadState& ts, ArrayT java_array, jint mod void ThrowAIOOBE(ScopedJniThreadState& ts, Array* array, jsize start, jsize length, const char* identifier) { std::string type(PrettyTypeOf(array)); - ts.Self()->ThrowNewException("Ljava/lang/ArrayIndexOutOfBoundsException;", + ts.Self()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;", "%s offset=%d length=%d %s.length=%d", type.c_str(), start, length, identifier, array->GetLength()); } void ThrowSIOOBE(ScopedJniThreadState& ts, jsize start, jsize length, jsize array_length) { - ts.Self()->ThrowNewException("Ljava/lang/StringIndexOutOfBoundsException;", + ts.Self()->ThrowNewExceptionF("Ljava/lang/StringIndexOutOfBoundsException;", "offset=%d length=%d string.length()=%d", start, length, array_length); } @@ -697,7 +697,7 @@ class JNI { return JNI_ERR; } ScopedLocalRef<jstring> s(env, env->NewStringUTF(msg)); - if (s.get() == NULL) { + if (msg != NULL && s.get() == NULL) { return JNI_ERR; } @@ -708,8 +708,6 @@ class JNI { return JNI_ERR; } - LOG(INFO) << "Throwing " << PrettyTypeOf(Decode<Throwable*>(ts, exception.get())) - << ": " << msg; ts.Self()->SetException(Decode<Throwable*>(ts, exception.get())); return JNI_OK; @@ -2824,7 +2822,7 @@ void* JavaVMExt::FindCodeForNativeMethod(Method* m) { } // throwing can cause libraries_lock to be reacquired if (native_method == NULL) { - Thread::Current()->ThrowNewException("Ljava/lang/UnsatisfiedLinkError;", "%s", detail.c_str()); + Thread::Current()->ThrowNewException("Ljava/lang/UnsatisfiedLinkError;", detail.c_str()); } return native_method; } diff --git a/src/jni_internal_test.cc b/src/jni_internal_test.cc index 74fdb0a..95e22ba 100644 --- a/src/jni_internal_test.cc +++ b/src/jni_internal_test.cc @@ -1360,9 +1360,17 @@ TEST_F(JniInternalTest, ThrowNew) { jclass exception_class = env_->FindClass("java/lang/RuntimeException"); ASSERT_TRUE(exception_class != NULL); + jthrowable thrown_exception; + EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, "hello world")); EXPECT_TRUE(env_->ExceptionCheck()); - jthrowable thrown_exception = env_->ExceptionOccurred(); + thrown_exception = env_->ExceptionOccurred(); + env_->ExceptionClear(); + EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class)); + + EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, NULL)); + EXPECT_TRUE(env_->ExceptionCheck()); + thrown_exception = env_->ExceptionOccurred(); env_->ExceptionClear(); EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class)); } diff --git a/src/monitor.cc b/src/monitor.cc index 4e71e45..6bd309d 100644 --- a/src/monitor.cc +++ b/src/monitor.cc @@ -367,7 +367,7 @@ void Monitor::Lock(Thread* self) { } void ThrowIllegalMonitorStateException(const char* msg) { - Thread::Current()->ThrowNewException("Ljava/lang/IllegalMonitorStateException;", "%s", msg); + Thread::Current()->ThrowNewException("Ljava/lang/IllegalMonitorStateException;", msg); } bool Monitor::Unlock(Thread* self) { @@ -469,7 +469,7 @@ void Monitor::Wait(Thread* self, int64_t ms, int32_t ns, bool interruptShouldThr // Enforce the timeout range. if (ms < 0 || ns < 0 || ns > 999999) { - Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;", "timeout arguments out of range: ms=%lld ns=%d", ms, ns); return; } @@ -582,7 +582,7 @@ done: */ self->interrupted_ = false; if (interruptShouldThrow) { - Thread::Current()->ThrowNewException("Ljava/lang/InterruptedException;", "%s", ""); + Thread::Current()->ThrowNewException("Ljava/lang/InterruptedException;", NULL); } } } diff --git a/src/object.cc b/src/object.cc index f8c9624..4a6e649 100644 --- a/src/object.cc +++ b/src/object.cc @@ -1225,13 +1225,13 @@ Array* Array::Alloc(Class* array_class, int32_t component_count) { } bool Array::ThrowArrayIndexOutOfBoundsException(int32_t index) const { - Thread::Current()->ThrowNewException("Ljava/lang/ArrayIndexOutOfBoundsException;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;", "length=%i; index=%i", length_, index); return false; } bool Array::ThrowArrayStoreException(Object* object) const { - Thread::Current()->ThrowNewException("Ljava/lang/ArrayStoreException;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;", "Can't store an element of type %s into an array of type %s", PrettyTypeOf(object).c_str(), PrettyTypeOf(this).c_str()); return false; @@ -1296,7 +1296,7 @@ uint16_t String::CharAt(int32_t index) const { // bounds check itself. if (index < 0 || index >= count_) { Thread* self = Thread::Current(); - self->ThrowNewException("Ljava/lang/StringIndexOutOfBoundsException;", + self->ThrowNewExceptionF("Ljava/lang/StringIndexOutOfBoundsException;", "length=%i; index=%i", count_, index); return 0; } diff --git a/src/reflection.cc b/src/reflection.cc index c560053..1294c08 100644 --- a/src/reflection.cc +++ b/src/reflection.cc @@ -77,7 +77,7 @@ jobject InvokeMethod(JNIEnv* env, jobject javaMethod, jobject javaReceiver, jobj ObjectArray<Class>* classes = Decode<ObjectArray<Class>*>(env, javaParams); int32_t arg_count = (objects != NULL) ? objects->GetLength() : 0; if (arg_count != classes->GetLength()) { - self->ThrowNewException("Ljava/lang/IllegalArgumentException;", + self->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;", "wrong number of arguments; expected %d, got %d", classes->GetLength(), arg_count); return NULL; @@ -219,7 +219,7 @@ bool ConvertPrimitiveValue(Class* src_class, Class* dst_class, const JValue& src default: break; } - Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;", "invalid primitive conversion from %s to %s", PrettyDescriptor(src_class->GetDescriptor()).c_str(), PrettyDescriptor(dst_class->GetDescriptor()).c_str()); @@ -333,7 +333,7 @@ bool UnboxPrimitive(JNIEnv* env, Object* o, Class* dst_class, JValue& unboxed_va src_class = class_linker->FindPrimitiveClass('S'); boxed_value.s = primitive_field->GetShort(o); } else { - Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;", "%s is not a boxed primitive type", PrettyDescriptor(src_descriptor).c_str()); return false; } diff --git a/src/runtime_support.cc b/src/runtime_support.cc index e5fbfd2..ca1fdea 100644 --- a/src/runtime_support.cc +++ b/src/runtime_support.cc @@ -83,7 +83,7 @@ extern "C" void artThrowNullPointerExceptionFromCode(Thread* thread, Method** sp // Place a special frame at the TOS that will save all callee saves *sp = Runtime::Current()->GetCalleeSaveMethod(); thread->SetTopOfStack(sp, 0); - thread->ThrowNewException("Ljava/lang/NullPointerException;", "unexpected null reference"); + thread->ThrowNewException("Ljava/lang/NullPointerException;", NULL); thread->DeliverException(); } @@ -101,8 +101,8 @@ extern "C" void artThrowArrayBoundsFromCode(int index, int limit, Thread* thread // Place a special frame at the TOS that will save all callee saves *sp = Runtime::Current()->GetCalleeSaveMethod(); thread->SetTopOfStack(sp, 0); - thread->ThrowNewException("Ljava/lang/ArrayIndexOutOfBoundsException;", - "length=%d; index=%d", limit, index); + thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;", "length=%d; index=%d", + limit, index); thread->DeliverException(); } @@ -110,9 +110,8 @@ extern "C" void artThrowArrayBoundsFromCode(int index, int limit, Thread* thread extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp) { *sp = Runtime::Current()->GetCalleeSaveMethod(); thread->SetTopOfStack(sp, 0); - thread->ThrowNewException("Ljava/lang/AbstractMethodError;", - "abstract method \"%s\"", - PrettyMethod(method).c_str()); + thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;", "abstract method \"%s\"", + PrettyMethod(method).c_str()); thread->DeliverException(); } @@ -122,9 +121,9 @@ extern "C" void artThrowStackOverflowFromCode(Method* method, Thread* thread, Me *sp = runtime->GetCalleeSaveMethod(); thread->SetTopOfStack(sp, 0); thread->SetStackEndForStackOverflow(); // Allow space on the stack for constructor to execute - thread->ThrowNewException("Ljava/lang/StackOverflowError;", - "stack size %zdkb; default stack size: %zdkb", - thread->GetStackSize() / KB, runtime->GetDefaultStackSize() / KB); + thread->ThrowNewExceptionF("Ljava/lang/StackOverflowError;", + "stack size %zdkb; default stack size: %zdkb", + thread->GetStackSize() / KB, runtime->GetDefaultStackSize() / KB); thread->ResetDefaultStackEnd(); // Return to default stack size thread->DeliverException(); } @@ -135,8 +134,8 @@ extern "C" void artThrowVerificationErrorFromCode(int32_t src1, int32_t ref, Thr *sp = runtime->GetCalleeSaveMethod(); thread->SetTopOfStack(sp, 0); LOG(WARNING) << "TODO: verifcation error detail message. src1=" << src1 << " ref=" << ref; - thread->ThrowNewException("Ljava/lang/VerifyError;", - "TODO: verifcation error detail message. src1=%d; ref=%d", src1, ref); + thread->ThrowNewExceptionF("Ljava/lang/VerifyError;", + "TODO: verification error detail message. src1=%d; ref=%d", src1, ref); thread->DeliverException(); } @@ -146,7 +145,7 @@ extern "C" void artThrowInternalErrorFromCode(int32_t errnum, Thread* thread, Me *sp = runtime->GetCalleeSaveMethod(); thread->SetTopOfStack(sp, 0); LOG(WARNING) << "TODO: internal error detail message. errnum=" << errnum; - thread->ThrowNewException("Ljava/lang/InternalError;", "errnum=%d", errnum); + thread->ThrowNewExceptionF("Ljava/lang/InternalError;", "errnum=%d", errnum); thread->DeliverException(); } @@ -156,7 +155,7 @@ extern "C" void artThrowRuntimeExceptionFromCode(int32_t errnum, Thread* thread, *sp = runtime->GetCalleeSaveMethod(); thread->SetTopOfStack(sp, 0); LOG(WARNING) << "TODO: runtime exception detail message. errnum=" << errnum; - thread->ThrowNewException("Ljava/lang/RuntimeException;", "errnum=%d", errnum); + thread->ThrowNewExceptionF("Ljava/lang/RuntimeException;", "errnum=%d", errnum); thread->DeliverException(); } @@ -166,7 +165,7 @@ extern "C" void artThrowNoSuchMethodFromCode(int32_t method_idx, Thread* thread, *sp = runtime->GetCalleeSaveMethod(); thread->SetTopOfStack(sp, 0); LOG(WARNING) << "TODO: no such method exception detail message. method_idx=" << method_idx; - thread->ThrowNewException("Ljava/lang/NoSuchMethodError;", "method_idx=%d", method_idx); + thread->ThrowNewExceptionF("Ljava/lang/NoSuchMethodError;", "method_idx=%d", method_idx); thread->DeliverException(); } @@ -176,7 +175,7 @@ extern "C" void artThrowNegArraySizeFromCode(int32_t size, Thread* thread, Metho Runtime* runtime = Runtime::Current(); *sp = runtime->GetCalleeSaveMethod(); thread->SetTopOfStack(sp, 0); - thread->ThrowNewException("Ljava/lang/NegativeArraySizeException;", "%d", size); + thread->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", size); thread->DeliverException(); } @@ -226,7 +225,7 @@ extern "C" Object* artAllocObjectFromCode(uint32_t type_idx, Method* method) { extern "C" Array* artCheckAndArrayAllocFromCode(uint32_t type_idx, Method* method, int32_t component_count) { if (component_count < 0) { - Thread::Current()->ThrowNewException("Ljava/lang/NegativeArraySizeException;", "%d", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count); return NULL; // Failure } @@ -240,11 +239,11 @@ extern "C" Array* artCheckAndArrayAllocFromCode(uint32_t type_idx, Method* metho } if (klass->IsPrimitive() && !klass->IsPrimitiveInt()) { if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) { - Thread::Current()->ThrowNewException("Ljava/lang/RuntimeException;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;", "Bad filled array request for type %s", PrettyDescriptor(klass->GetDescriptor()).c_str()); } else { - Thread::Current()->ThrowNewException("Ljava/lang/InternalError;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/InternalError;", "Found type %s; filled-new-array not implemented for anything but \'int\'", PrettyDescriptor(klass->GetDescriptor()).c_str()); } @@ -259,7 +258,7 @@ extern "C" Array* artCheckAndArrayAllocFromCode(uint32_t type_idx, Method* metho // it cannot be resolved, throw an error. If it can, use it to create an array. extern "C" Array* artArrayAllocFromCode(uint32_t type_idx, Method* method, int32_t component_count) { if (component_count < 0) { - Thread::Current()->ThrowNewException("Ljava/lang/NegativeArraySizeException;", "%d", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count); return NULL; // Failure } @@ -282,7 +281,7 @@ extern "C" int artCheckCastFromCode(const Class* a, const Class* b) { if (b->IsAssignableFrom(a)) { return 0; // Success } else { - Thread::Current()->ThrowNewException("Ljava/lang/ClassCastException;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassCastException;", "%s cannot be cast to %s", PrettyDescriptor(a->GetDescriptor()).c_str(), PrettyDescriptor(b->GetDescriptor()).c_str()); @@ -300,7 +299,7 @@ extern "C" int artCanPutArrayElementFromCode(const Object* element, const Class* if (component_type->IsAssignableFrom(element_class)) { return 0; // Success } else { - Thread::Current()->ThrowNewException("Ljava/lang/ArrayStoreException;", + Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;", "Cannot store an object of type %s in to an array of type %s", PrettyDescriptor(element_class->GetDescriptor()).c_str(), PrettyDescriptor(array_class->GetDescriptor()).c_str()); @@ -343,16 +342,15 @@ extern "C" void artCheckSuspendFromCode(Thread* thread) { extern "C" int artHandleFillArrayDataFromCode(Array* array, const uint16_t* table) { DCHECK_EQ(table[0], 0x0300); if (array == NULL) { - Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", - "null array in fill array"); + Thread::Current()->ThrowNewExceptionF("Ljava/lang/NullPointerException;", + "null array in fill array"); return -1; // Error } DCHECK(array->IsArrayInstance() && !array->IsObjectArray()); uint32_t size = (uint32_t)table[2] | (((uint32_t)table[3]) << 16); if (static_cast<int32_t>(size) > array->GetLength()) { - Thread::Current()->ThrowNewException("Ljava/lang/ArrayIndexOutOfBoundsException;", - "failed array fill. length=%d; index=%d", - array->GetLength(), size); + Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;", + "failed array fill. length=%d; index=%d", array->GetLength(), size); return -1; // Error } uint16_t width = table[1]; @@ -367,8 +365,8 @@ extern "C" uint64_t artFindInterfaceMethodInCacheFromCode(uint32_t method_idx, Method* caller_method) { Thread* thread = Thread::Current(); if (this_object == NULL) { - thread->ThrowNewException("Ljava/lang/NullPointerException;", - "null receiver during interface dispatch"); + thread->ThrowNewExceptionF("Ljava/lang/NullPointerException;", + "null receiver during interface dispatch"); return 0; } ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); diff --git a/src/thread.cc b/src/thread.cc index 0df4929..0dd3766 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -1076,7 +1076,7 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray(JNIEnv* env, job return result; } -void Thread::ThrowNewException(const char* exception_class_descriptor, const char* fmt, ...) { +void Thread::ThrowNewExceptionF(const char* exception_class_descriptor, const char* fmt, ...) { va_list args; va_start(args, fmt); ThrowNewExceptionV(exception_class_descriptor, fmt, args); @@ -1086,7 +1086,10 @@ void Thread::ThrowNewException(const char* exception_class_descriptor, const cha void Thread::ThrowNewExceptionV(const char* exception_class_descriptor, const char* fmt, va_list ap) { std::string msg; StringAppendV(&msg, fmt, ap); + ThrowNewException(exception_class_descriptor, msg.c_str()); +} +void Thread::ThrowNewException(const char* exception_class_descriptor, const char* msg) { // Convert "Ljava/lang/Exception;" into JNI-style "java/lang/Exception". CHECK_EQ('L', exception_class_descriptor[0]); std::string descriptor(exception_class_descriptor + 1); @@ -1096,7 +1099,7 @@ void Thread::ThrowNewExceptionV(const char* exception_class_descriptor, const ch JNIEnv* env = GetJniEnv(); jclass exception_class = env->FindClass(descriptor.c_str()); CHECK(exception_class != NULL) << "descriptor=\"" << descriptor << "\""; - int rc = env->ThrowNew(exception_class, msg.c_str()); + int rc = env->ThrowNew(exception_class, msg); CHECK_EQ(rc, JNI_OK); env->DeleteLocalRef(exception_class); } diff --git a/src/thread.h b/src/thread.h index e9491dd..4f85b70 100644 --- a/src/thread.h +++ b/src/thread.h @@ -360,7 +360,10 @@ class PACKED Thread { top_of_managed_stack_pc_ = pc; } - void ThrowNewException(const char* exception_class_descriptor, const char* fmt, ...) + // 'msg' may be NULL. + void ThrowNewException(const char* exception_class_descriptor, const char* msg); + + void ThrowNewExceptionF(const char* exception_class_descriptor, const char* fmt, ...) __attribute__ ((format(printf, 3, 4))); void ThrowNewExceptionV(const char* exception_class_descriptor, const char* fmt, va_list ap); diff --git a/test/034-call-null/expected.txt b/test/034-call-null/expected.txt index 5ffbe05..7697a32 100644 --- a/test/034-call-null/expected.txt +++ b/test/034-call-null/expected.txt @@ -1,3 +1,2 @@ java.lang.NullPointerException at Main.main(Main.java:12) - at dalvik.system.NativeStart.main(Native Method) diff --git a/test/038-inner-null/expected.txt b/test/038-inner-null/expected.txt index 0be8ffd..6932c50 100644 --- a/test/038-inner-null/expected.txt +++ b/test/038-inner-null/expected.txt @@ -2,4 +2,3 @@ new Special() java.lang.NullPointerException at Main$Special.callInner(Main.java:17) at Main.main(Main.java:6) - at dalvik.system.NativeStart.main(Native Method) diff --git a/test/054-uncaught/expected.txt b/test/054-uncaught/expected.txt index e7473be..e443a07 100644 --- a/test/054-uncaught/expected.txt +++ b/test/054-uncaught/expected.txt @@ -18,4 +18,3 @@ Uncaught exception DEFAULT! java.lang.NullPointerException: Hi diddly-ho, neighborino. at Main.catchTheUncaught(Main.java:49) at Main.main(Main.java:12) - at dalvik.system.NativeStart.main(Native Method) |