summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/class_linker.cc24
-rw-r--r--src/dalvik_system_VMRuntime.cc2
-rw-r--r--src/java_lang_Class.cc25
-rw-r--r--src/java_lang_System.cc9
-rw-r--r--src/java_lang_reflect_Constructor.cc2
-rw-r--r--src/java_lang_reflect_Field.cc4
-rw-r--r--src/jni_internal.cc16
-rw-r--r--src/jni_internal_test.cc10
-rw-r--r--src/monitor.cc6
-rw-r--r--src/object.cc6
-rw-r--r--src/reflection.cc6
-rw-r--r--src/runtime_support.cc54
-rw-r--r--src/thread.cc7
-rw-r--r--src/thread.h5
-rw-r--r--test/034-call-null/expected.txt1
-rw-r--r--test/038-inner-null/expected.txt1
-rw-r--r--test/054-uncaught/expected.txt1
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)