From 3d49173b0b211249bdef215d58322cc68a4396fb Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 9 Dec 2010 19:38:12 -0700 Subject: [PATCH] avoid inifinite recursion if java.lang.Object is missing; refactoring When trying to create an array class, we try to resolve java.lang.Object so we can use its vtable in the array class. However, if Object is missing, we'll try to create and throw a ClassNotFoundException, which requires creating an array to store the stack trace, which requires creating an array class, which requires resolving Object, etc.. This commit short-circuits this process by telling resolveClass not to create and throw an exception if it can't find Object. While doing the above work, I noticed that the implementations of Classpath::makeThrowable in classpath-avian.cpp and classpath-openjdk.cpp were identical, so I made makeThrowable a top-level function. Finally, I discovered that Thread.setDaemon can only be called before the target thread has been started, which allowed me to simplify the code to track daemon threads in the VM. --- classpath/java/lang/Thread.java | 8 +- src/builtin.cpp | 12 +-- src/classpath-avian.cpp | 45 ++-------- src/classpath-common.h | 10 +-- src/classpath-openjdk.cpp | 50 +++-------- src/compile.cpp | 31 +++---- src/interpret.cpp | 137 +++++++++++----------------- src/jnienv.cpp | 20 ++--- src/machine.cpp | 83 ++++++----------- src/machine.h | 153 ++++++++++++++++++++------------ src/process.cpp | 2 +- 11 files changed, 219 insertions(+), 332 deletions(-) diff --git a/classpath/java/lang/Thread.java b/classpath/java/lang/Thread.java index 0606f51377..2d321193a0 100644 --- a/classpath/java/lang/Thread.java +++ b/classpath/java/lang/Thread.java @@ -239,12 +239,12 @@ public class Thread implements Runnable { } public synchronized void setDaemon(boolean v) { - if (v != daemon) { - setDaemon(this, v); + if (getState() != State.NEW) { + throw new IllegalStateException(); } - } - private static native void setDaemon(Thread t, boolean increment); + daemon = v; + } public static native void yield(); diff --git a/src/builtin.cpp b/src/builtin.cpp index 3c0365ea7b..dd8ece531a 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -40,8 +40,7 @@ search(Thread* t, object loader, object name, return reinterpret_cast(r); } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + t->exception = makeThrowable(t, Machine::NullPointerExceptionType); return 0; } } @@ -93,8 +92,7 @@ Avian_avian_SystemClassLoader_resourceExists return r; } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + t->exception = makeThrowable(t, Machine::NullPointerExceptionType); return 0; } } @@ -126,8 +124,7 @@ Avian_avian_Machine_dumpHeap fclose(out); } else { object message = makeString(t, "file not found: %s", n); - t->exception = t->m->classpath->makeThrowable - (t, Machine::RuntimeExceptionType, message); + t->exception = makeThrowable(t, Machine::RuntimeExceptionType, message); } } @@ -183,8 +180,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_open return reinterpret_cast(r); } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + t->exception = makeThrowable(t, Machine::NullPointerExceptionType); return 0; } } diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 8bc2560086..51f5058713 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -65,27 +65,6 @@ class MyClasspath : public Classpath { } } - virtual object - makeThrowable - (Thread* t, Machine::Type type, object message, object trace, object cause) - { - PROTECT(t, message); - PROTECT(t, trace); - PROTECT(t, cause); - - if (trace == 0) { - trace = makeTrace(t); - } - - object result = make(t, vm::type(t, type)); - - set(t, result, ThrowableMessage, message); - set(t, result, ThrowableTrace, trace); - set(t, result, ThrowableCause, cause); - - return result; - } - virtual void boot(Thread*) { @@ -330,7 +309,7 @@ Avian_java_lang_reflect_Method_invoke object v = t->m->processor->invokeArray(t, method, instance, args); if (t->exception) { - t->exception = t->m->classpath->makeThrowable + t->exception = makeThrowable (t, Machine::InvocationTargetExceptionType, 0, 0, t->exception); } return reinterpret_cast(v); @@ -348,12 +327,10 @@ Avian_java_lang_reflect_Array_getLength if (LIKELY(elementSize)) { return cast(array, BytesPerWord); } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::IllegalArgumentExceptionType); + t->exception = makeThrowable(t, Machine::IllegalArgumentExceptionType); } } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + t->exception = makeThrowable(t, Machine::NullPointerExceptionType); } return 0; } @@ -462,8 +439,7 @@ Avian_java_lang_System_identityHashCode if (LIKELY(o)) { return objectHash(t, o); } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + t->exception = makeThrowable(t, Machine::NullPointerExceptionType); return 0; } } @@ -604,16 +580,6 @@ Avian_java_lang_Thread_enumerate return count; } -extern "C" JNIEXPORT void JNICALL -Avian_java_lang_Thread_setDaemon -(Thread* t, object, uintptr_t* arguments) -{ - object thread = reinterpret_cast(arguments[0]); - bool daemon = arguments[1] != 0; - - setDaemon(t, thread, daemon); -} - extern "C" JNIEXPORT void JNICALL Avian_avian_Classes_acquireClassLock (Thread* t, object, uintptr_t*) @@ -682,8 +648,7 @@ Avian_avian_Classes_isAssignableFrom if (LIKELY(that)) { return vm::isAssignableFrom(t, this_, that); } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + t->exception = makeThrowable(t, Machine::NullPointerExceptionType); return 0; } } diff --git a/src/classpath-common.h b/src/classpath-common.h index 3ca61210a0..7d17a74673 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -101,7 +101,7 @@ arrayCopy(Thread* t, object src, int32_t srcOffset, object dst, return; } else { - t->exception = t->m->classpath->makeThrowable + t->exception = makeThrowable (t, Machine::IndexOutOfBoundsExceptionType); return; } @@ -111,13 +111,11 @@ arrayCopy(Thread* t, object src, int32_t srcOffset, object dst, } } } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + t->exception = makeThrowable(t, Machine::NullPointerExceptionType); return; } - t->exception = t->m->classpath->makeThrowable - (t, Machine::ArrayStoreExceptionType); + t->exception = makeThrowable(t, Machine::ArrayStoreExceptionType); } void @@ -223,7 +221,7 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName, } } else { object message = makeString(t, "library not found: %s", name); - t->exception = t->m->classpath->makeThrowable + t->exception = makeThrowable (t, Machine::UnsatisfiedLinkErrorType, message); } diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index eda7ac90de..c18445d298 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -330,27 +330,6 @@ class MyClasspath : public Classpath { release(t, t->javaThread); } - virtual object - makeThrowable - (Thread* t, Machine::Type type, object message, object trace, object cause) - { - PROTECT(t, message); - PROTECT(t, trace); - PROTECT(t, cause); - - if (trace == 0) { - trace = makeTrace(t); - } - - object result = make(t, vm::type(t, type)); - - set(t, result, ThrowableMessage, message); - set(t, result, ThrowableTrace, trace); - set(t, result, ThrowableCause, cause); - - return result; - } - virtual void boot(Thread* t) { @@ -709,22 +688,19 @@ openFile(Thread* t, object method, uintptr_t* arguments) EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), stringLength(t, path)); if (ef.jar) { if (ef.jarLength == 0 or ef.pathLength == 0) { - t->exception = t->m->classpath->makeThrowable - (t, Machine::FileNotFoundExceptionType); + t->exception = makeThrowable(t, Machine::FileNotFoundExceptionType); return; } Finder* finder = getFinder(t, ef.jar, ef.jarLength); if (finder == 0) { - t->exception = t->m->classpath->makeThrowable - (t, Machine::FileNotFoundExceptionType); + t->exception = makeThrowable(t, Machine::FileNotFoundExceptionType); return; } System::Region* r = finder->find(ef.path); if (r == 0) { - t->exception = t->m->classpath->makeThrowable - (t, Machine::FileNotFoundExceptionType); + t->exception = makeThrowable(t, Machine::FileNotFoundExceptionType); return; } @@ -792,8 +768,7 @@ readByteFromFile(Thread* t, object method, uintptr_t* arguments) return -1; } } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::IoExceptionType); + t->exception = makeThrowable(t, Machine::IoExceptionType); return 0; } } else { @@ -847,8 +822,7 @@ readBytesFromFile(Thread* t, object method, uintptr_t* arguments) return length; } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::IoExceptionType); + t->exception = makeThrowable(t, Machine::IoExceptionType); return 0; } } else { @@ -892,8 +866,7 @@ skipBytesInFile(Thread* t, object method, uintptr_t* arguments) return count; } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::IoExceptionType); + t->exception = makeThrowable(t, Machine::IoExceptionType); return 0; } } else { @@ -927,8 +900,7 @@ availableBytesInFile(Thread* t, object method, uintptr_t* arguments) return static_cast(regionRegion(t, region))->length() - regionPosition(t, region); } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::IoExceptionType); + t->exception = makeThrowable(t, Machine::IoExceptionType); return 0; } } else { @@ -1735,8 +1707,7 @@ Avian_sun_misc_Unsafe_allocateMemory if (p) { return reinterpret_cast(p); } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::OutOfMemoryErrorType); + t->exception = makeThrowable(t, Machine::OutOfMemoryErrorType); return 0; } } @@ -2474,8 +2445,7 @@ EXPORT(JVM_FindPrimitiveClass)(Thread* t, const char* name) return makeLocalReference (t, getJClass(t, type(t, Machine::JvoidType))); default: - t->exception = t->m->classpath->makeThrowable - (t, Machine::IllegalArgumentExceptionType); + t->exception = makeThrowable(t, Machine::IllegalArgumentExceptionType); return 0; } } @@ -2494,7 +2464,7 @@ EXPORT(JVM_FindClassFromClassLoader)(Thread* t, const char* name, (t, loader ? *loader : root(t, Machine::BootLoader), name); if (t->exception) { if (throwError) { - t->exception = t->m->classpath->makeThrowable + t->exception = makeThrowable (t, Machine::NoClassDefFoundErrorType, throwableMessage(t, t->exception), throwableTrace(t, t->exception), diff --git a/src/compile.cpp b/src/compile.cpp index 3bafb38eff..6cdd70f5e7 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -2150,8 +2150,7 @@ findInterfaceMethodFromInstance(MyThread* t, object method, object instance) return methodAddress(t, target); } } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + t->exception = makeThrowable(t, Machine::NullPointerExceptionType); unwind(t); } } @@ -2422,7 +2421,7 @@ makeBlankObjectArray(MyThread* t, object class_, int32_t length) return reinterpret_cast(makeObjectArray(t, class_, length)); } else { object message = makeString(t, "%d", length); - t->exception = t->m->classpath->makeThrowable + t->exception = makeThrowable (t, Machine::NegativeArraySizeExceptionType, message); unwind(t); } @@ -2472,7 +2471,7 @@ makeBlankArray(MyThread* t, unsigned type, int32_t length) return reinterpret_cast(constructor(t, length)); } else { object message = makeString(t, "%d", length); - t->exception = t->m->classpath->makeThrowable + t->exception = makeThrowable (t, Machine::NegativeArraySizeExceptionType, message); unwind(t); } @@ -2507,8 +2506,7 @@ setMaybeNull(MyThread* t, object o, unsigned offset, object value) if (LIKELY(o)) { set(t, o, offset, value); } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + t->exception = makeThrowable(t, Machine::NullPointerExceptionType); unwind(t); } } @@ -2519,8 +2517,7 @@ acquireMonitorForObject(MyThread* t, object o) if (LIKELY(o)) { acquire(t, o); } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + t->exception = makeThrowable(t, Machine::NullPointerExceptionType); unwind(t); } } @@ -2531,8 +2528,7 @@ releaseMonitorForObject(MyThread* t, object o) if (LIKELY(o)) { release(t, o); } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + t->exception = makeThrowable(t, Machine::NullPointerExceptionType); unwind(t); } } @@ -2548,7 +2544,7 @@ makeMultidimensionalArray2(MyThread* t, object class_, uintptr_t* countStack, RUNTIME_ARRAY_BODY(counts)[i] = countStack[dimensions - i - 1]; if (UNLIKELY(RUNTIME_ARRAY_BODY(counts)[i] < 0)) { object message = makeString(t, "%d", RUNTIME_ARRAY_BODY(counts)[i]); - t->exception = t->m->classpath->makeThrowable + t->exception = makeThrowable (t, Machine::NegativeArraySizeExceptionType, message); return 0; } @@ -2603,7 +2599,7 @@ throwArrayIndexOutOfBounds(MyThread* t) { if (ensure(t, FixedSizeOfArrayIndexOutOfBoundsException + traceSize(t))) { atomicOr(&(t->flags), Thread::TracingFlag); - t->exception = t->m->classpath->makeThrowable + t->exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType); atomicAnd(&(t->flags), ~Thread::TracingFlag); } else { @@ -2621,8 +2617,7 @@ throw_(MyThread* t, object o) if (LIKELY(o)) { t->exception = o; } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + t->exception = makeThrowable(t, Machine::NullPointerExceptionType); } // printTrace(t, t->exception); @@ -2638,8 +2633,7 @@ checkCast(MyThread* t, object class_, object o) (t, "%s as %s", &byteArrayBody(t, className(t, objectClass(t, o)), 0), &byteArrayBody(t, className(t, class_), 0)); - t->exception = t->m->classpath->makeThrowable - (t, Machine::ClassCastExceptionType, message); + t->exception = makeThrowable(t, Machine::ClassCastExceptionType, message); unwind(t); } } @@ -6837,7 +6831,7 @@ callContinuation(MyThread* t, object continuation, object result, action = Call; } } else { - t->exception = t->m->classpath->makeThrowable + t->exception = makeThrowable (t, Machine::IncompatibleContinuationExceptionType); action = Throw; } @@ -7175,8 +7169,7 @@ class SegFaultHandler: public System::SignalHandler { if (ensure(t, FixedSizeOfNullPointerException + traceSize(t))) { atomicOr(&(t->flags), Thread::TracingFlag); - t->exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + t->exception = makeThrowable(t, Machine::NullPointerExceptionType); atomicAnd(&(t->flags), ~Thread::TracingFlag); } else { // not enough memory available for a new NPE and stack trace diff --git a/src/interpret.cpp b/src/interpret.cpp index 1634463ea1..e9d4c418c1 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -438,8 +438,7 @@ checkStack(Thread* t, object method) + codeMaxStack(t, methodCode(t, method)) > Thread::StackSizeInWords / 2)) { - t->exception = t->m->classpath->makeThrowable - (t, Machine::StackOverflowErrorType); + t->exception = makeThrowable(t, Machine::StackOverflowErrorType); } } @@ -864,13 +863,12 @@ interpret(Thread* t) } else { object message = makeString (t, "%d not in [0,%d)", index, objectArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -888,13 +886,12 @@ interpret(Thread* t) } else { object message = makeString (t, "%d not in [0,%d)", index, objectArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -935,7 +932,7 @@ interpret(Thread* t) pushObject(t, makeObjectArray(t, class_, count)); } else { object message = makeString(t, "%d", count); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::NegativeArraySizeExceptionType, message); goto throw_; } @@ -957,8 +954,7 @@ interpret(Thread* t) if (LIKELY(array)) { pushInt(t, cast(array, BytesPerWord)); } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -986,8 +982,7 @@ interpret(Thread* t) case athrow: { exception = popObject(t); if (UNLIKELY(exception == 0)) { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); } } goto throw_; @@ -1005,7 +1000,7 @@ interpret(Thread* t) } else { object message = makeString(t, "%d not in [0,%d)", index, booleanArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } @@ -1019,14 +1014,13 @@ interpret(Thread* t) object message = makeString(t, "%d not in [0,%d)", index, byteArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -1046,7 +1040,7 @@ interpret(Thread* t) } else { object message = makeString(t, "%d not in [0,%d)", index, booleanArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } @@ -1058,14 +1052,13 @@ interpret(Thread* t) } else { object message = makeString(t, "%d not in [0,%d)", index, byteArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -1086,13 +1079,12 @@ interpret(Thread* t) } else { object message = makeString(t, "%d not in [0,%d)", index, charArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -1110,13 +1102,12 @@ interpret(Thread* t) } else { object message = makeString(t, "%d not in [0,%d)", index, charArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -1134,7 +1125,7 @@ interpret(Thread* t) &byteArrayBody (t, className(t, objectClass(t, peekObject(t, sp - 1))), 0), &byteArrayBody(t, className(t, class_), 0)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ClassCastExceptionType, message); goto throw_; } @@ -1172,13 +1163,12 @@ interpret(Thread* t) } else { object message = makeString(t, "%d not in [0,%d)", index, doubleArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -1196,13 +1186,12 @@ interpret(Thread* t) } else { object message = makeString(t, "%d not in [0,%d)", index, doubleArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -1376,13 +1365,12 @@ interpret(Thread* t) } else { object message = makeString(t, "%d not in [0,%d)", index, floatArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -1400,13 +1388,12 @@ interpret(Thread* t) } else { object message = makeString(t, "%d not in [0,%d)", index, floatArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -1518,8 +1505,7 @@ interpret(Thread* t) } } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -1611,13 +1597,12 @@ interpret(Thread* t) } else { object message = makeString(t, "%d not in [0,%d)", index, intArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -1642,13 +1627,12 @@ interpret(Thread* t) } else { object message = makeString(t, "%d not in [0,%d)", index, intArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -1915,8 +1899,7 @@ interpret(Thread* t) (t, method, objectClass(t, peekObject(t, sp - parameterFootprint))); goto invoke; } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -1941,8 +1924,7 @@ interpret(Thread* t) goto invoke; } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -1973,8 +1955,7 @@ interpret(Thread* t) code = findVirtualMethod(t, method, class_); goto invoke; } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -2110,13 +2091,12 @@ interpret(Thread* t) } else { object message = makeString(t, "%d not in [0,%d)", index, longArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -2141,13 +2121,12 @@ interpret(Thread* t) } else { object message = makeString(t, "%d not in [0,%d)", index, longArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -2373,8 +2352,7 @@ interpret(Thread* t) if (LIKELY(o)) { acquire(t, o); } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -2384,8 +2362,7 @@ interpret(Thread* t) if (LIKELY(o)) { release(t, o); } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -2403,7 +2380,7 @@ interpret(Thread* t) counts[i] = popInt(t); if (UNLIKELY(counts[i] < 0)) { object message = makeString(t, "%d", counts[i]); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::NegativeArraySizeExceptionType, message); goto throw_; } @@ -2477,7 +2454,7 @@ interpret(Thread* t) pushObject(t, array); } else { object message = makeString(t, "%d", count); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::NegativeArraySizeExceptionType, message); goto throw_; } @@ -2540,8 +2517,7 @@ interpret(Thread* t) break; } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); } } break; @@ -2552,8 +2528,7 @@ interpret(Thread* t) if (LIKELY(o)) { cast(o, fieldOffset(t, field)) = value; } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); } } break; @@ -2563,8 +2538,7 @@ interpret(Thread* t) if (LIKELY(o)) { set(t, o, fieldOffset(t, field), value); } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); } } break; @@ -2694,13 +2668,12 @@ interpret(Thread* t) } else { object message = makeString(t, "%d not in [0,%d)", index, shortArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -2718,13 +2691,12 @@ interpret(Thread* t) } else { object message = makeString(t, "%d not in [0,%d)", index, shortArrayLength(t, array)); - exception = t->m->classpath->makeThrowable + exception = makeThrowable (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); goto throw_; } } else { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); goto throw_; } } goto loop; @@ -3166,8 +3138,7 @@ class MyProcessor: public Processor { if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1 > Thread::StackSizeInWords / 2)) { - t->exception = t->m->classpath->makeThrowable - (t, Machine::StackOverflowErrorType); + t->exception = makeThrowable(t, Machine::StackOverflowErrorType); return 0; } @@ -3192,8 +3163,7 @@ class MyProcessor: public Processor { if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1 > Thread::StackSizeInWords / 2)) { - t->exception = t->m->classpath->makeThrowable - (t, Machine::StackOverflowErrorType); + t->exception = makeThrowable(t, Machine::StackOverflowErrorType); return 0; } @@ -3217,8 +3187,7 @@ class MyProcessor: public Processor { if (UNLIKELY(t->sp + parameterFootprint(vmt, methodSpec, false) > Thread::StackSizeInWords / 2)) { - t->exception = t->m->classpath->makeThrowable - (t, Machine::StackOverflowErrorType); + t->exception = makeThrowable(t, Machine::StackOverflowErrorType); return 0; } diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 7579b9891e..38598a385a 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -31,26 +31,17 @@ AttachCurrentThread(Machine* m, Thread** t, void*) { *t = static_cast(m->localThread->get()); if (*t == 0) { - *t = m->processor->makeThread(m, 0, m->rootThread); - m->system->attach(&((*t)->runnable)); - - enter(*t, Thread::ActiveState); - enter(*t, Thread::IdleState); - - m->localThread->set(*t); + *t = attachThread(m, false); } return 0; } jint JNICALL -AttachCurrentThreadAsDaemon(Machine* m, Thread** t, void* parameters) +AttachCurrentThreadAsDaemon(Machine* m, Thread** t, void*) { *t = static_cast(m->localThread->get()); if (*t == 0) { - AttachCurrentThread(m, t, parameters); - - ENTER(*t, Thread::ActiveState); - setDaemon(*t, (*t)->javaThread, true); + *t = attachThread(m, true); } return 0; } @@ -2040,13 +2031,12 @@ boot(Thread* t) enter(t, Thread::ActiveState); if (t->exception == 0) { - setRoot(t, Machine::NullPointerException, t->m->classpath->makeThrowable + setRoot(t, Machine::NullPointerException, makeThrowable (t, Machine::NullPointerExceptionType)); if (t->exception == 0) { setRoot(t, Machine::ArrayIndexOutOfBoundsException, - t->m->classpath->makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType)); + makeThrowable(t, Machine::ArrayIndexOutOfBoundsExceptionType)); } } diff --git a/src/machine.cpp b/src/machine.cpp index ec1c06ae61..ddf27487b1 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1731,11 +1731,13 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec, PROTECT(t, spec); PROTECT(t, elementClass); + // Load java.lang.Object if present so we can use its vtable, but + // don't throw an exception if we can't find it. This way, we + // avoid infinite recursion due to trying to create an array to + // make a stack trace for a ClassNotFoundException. resolveSystemClass (t, root(t, Machine::BootLoader), - className(t, type(t, Machine::JobjectType))); - - if (UNLIKELY(t->exception)) return 0; + className(t, type(t, Machine::JobjectType)), false); } object vtable = classVirtualTable(t, type(t, Machine::JobjectType)); @@ -2324,18 +2326,16 @@ Thread::init() setRoot(this, Machine::JNIMethodTable, makeVector(this, 0, 0)); m->localThread->set(this); + + javaThread = m->classpath->makeThread(this, 0); + + threadPeer(this, javaThread) = reinterpret_cast(this); } else { peer = parent->child; parent->child = this; } expect(this, m->system->success(m->system->make(&lock))); - - if (javaThread == 0) { - this->javaThread = m->classpath->makeThread(this, parent); - } - - threadPeer(this, javaThread) = reinterpret_cast(this); } void @@ -2494,36 +2494,6 @@ enter(Thread* t, Thread::State s) } break; case Thread::IdleState: - // The java.lang.Thread implementation may or may not notify the - // VM when the daemon field in the Java object changes, so we sync - // up the native field whenever the thread transitions to idle: - - // todo: this won't always help if some other thread sets the - // daemon field. The thread trying to shut down the VM really - // just needs to count from scratch every time any thread makes a - // transition (i.e. eliminate Machine::daemonCount). - - if (UNLIKELY(((t->flags & Thread::DaemonFlag) != 0) - != threadDaemon(t, t->javaThread))) - { - ACQUIRE_LOCK; - - if (threadDaemon(t, t->javaThread)) { - atomicOr(&(t->flags), Thread::DaemonFlag); - } else { - atomicAnd(&(t->flags), ~Thread::DaemonFlag); - } - - if (t->flags & Thread::DaemonFlag) { - ++ t->m->daemonCount; - } else { - expect(t, t->m->daemonCount); - -- t->m->daemonCount; - } - - t->m->stateLock->notifyAll(t->systemThread); - } - if (LIKELY(t->state == Thread::ActiveState)) { // fast path assert(t, t->m->activeCount > 0); @@ -2563,7 +2533,7 @@ enter(Thread* t, Thread::State s) assert(t, t->m->liveCount > 0); -- t->m->liveCount; - if (threadDaemon(t, t->javaThread)) { + if (t->flags & Thread::DaemonFlag) { -- t->m->daemonCount; } } @@ -3239,7 +3209,7 @@ resolveSystemClass(Thread* t, object loader, object spec, bool throw_) hashMapInsert(t, classLoaderMap(t, loader), spec, class_, byteArrayHash); } else if (throw_ and t->exception == 0) { object message = makeString(t, "%s", &byteArrayBody(t, spec, 0)); - t->exception = t->m->classpath->makeThrowable + t->exception = makeThrowable (t, Machine::ClassNotFoundExceptionType, message); } } @@ -3334,7 +3304,7 @@ resolveClass(Thread* t, object loader, object spec, bool throw_) } else { if (t->exception == 0) { object message = makeString(t, "%s", &byteArrayBody(t, spec, 0)); - t->exception = t->m->classpath->makeThrowable + t->exception = makeThrowable (t, Machine::ClassNotFoundExceptionType, message); } @@ -3361,8 +3331,7 @@ resolveMethod(Thread* t, object class_, const char* methodName, (t, "%s %s not found in %s", methodName, methodSpec, &byteArrayBody(t, className(t, class_), 0)); - t->exception = t->m->classpath->makeThrowable - (t, Machine::NoSuchMethodErrorType, message); + t->exception = makeThrowable(t, Machine::NoSuchMethodErrorType, message); return 0; } else { return method; @@ -3395,8 +3364,7 @@ resolveField(Thread* t, object class_, const char* fieldName, (t, "%s %s not found in %s", fieldName, fieldSpec, &byteArrayBody(t, className(t, class_), 0)); - t->exception = t->m->classpath->makeThrowable - (t, Machine::NoSuchFieldErrorType, message); + t->exception = makeThrowable(t, Machine::NoSuchFieldErrorType, message); return 0; } else { return field; @@ -3449,7 +3417,7 @@ preInitClass(Thread* t, object c) object message = makeString (t, "%s", &byteArrayBody(t, className(t, c), 0)); - t->exception = t->m->classpath->makeThrowable + t->exception = makeThrowable (t, Machine::NoClassDefFoundErrorType, message); } else { classVmFlags(t, c) |= InitFlag; @@ -3467,7 +3435,7 @@ postInitClass(Thread* t, object c) ACQUIRE(t, t->m->classLock); if (t->exception) { - t->exception = t->m->classpath->makeThrowable + t->exception = makeThrowable (t, Machine::ExceptionInInitializerErrorType, 0, 0, t->exception); classVmFlags(t, c) |= NeedInitFlag | InitErrorFlag; @@ -3527,6 +3495,7 @@ resolveObjectArrayClass(Thread* t, object loader, object elementClass) } object arrayClass = resolveClass(t, loader, spec); + if (UNLIKELY(t->exception)) return 0; set(t, getClassRuntimeData(t, elementClass), ClassRuntimeDataArrayClass, arrayClass); @@ -3539,6 +3508,8 @@ makeObjectArray(Thread* t, object elementClass, unsigned count) { object arrayClass = resolveObjectArrayClass (t, classLoader(t, elementClass), elementClass); + if (UNLIKELY(t->exception)) return 0; + PROTECT(t, arrayClass); object array = makeArray(t, count); @@ -3760,13 +3731,12 @@ collect(Thread* t, Heap::CollectionType type) } if (root(t, Machine::ObjectsToFinalize) and m->finalizeThread == 0) { - m->finalizeThread = m->processor->makeThread - (m, t->m->classpath->makeThread(t, m->rootThread), m->rootThread); + object javaThread = t->m->classpath->makeThread(t, m->rootThread); + threadDaemon(t, javaThread) = true; - if (not t->m->system->success - (m->system->start(&(m->finalizeThread->runnable)))) - { - m->finalizeThread->exit(); + m->finalizeThread = m->processor->makeThread(m, javaThread, m->rootThread); + + if (not startThread(t, m->finalizeThread)) { m->finalizeThread = 0; } } @@ -3849,8 +3819,7 @@ void printTrace(Thread* t, object exception) { if (exception == 0) { - exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); + exception = makeThrowable(t, Machine::NullPointerExceptionType); } for (object e = exception; e; e = throwableCause(t, e)) { @@ -3956,8 +3925,6 @@ makeTrace(Thread* t, Thread* target) void runFinalizeThread(Thread* t) { - setDaemon(t, t->javaThread, true); - object list = 0; PROTECT(t, list); diff --git a/src/machine.h b/src/machine.h index 4c65230095..984d4e54db 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1282,6 +1282,9 @@ runJavaThread(Thread* t); void runFinalizeThread(Thread* t); +void +checkDaemon(Thread* t); + class Thread { public: enum State { @@ -1361,6 +1364,8 @@ class Thread { t->m->localThread->set(t); + checkDaemon(t); + if (t == t->m->finalizeThread) { runFinalizeThread(t); } else if (t->javaThread) { @@ -1429,11 +1434,6 @@ class Classpath { virtual void runThread(Thread* t) = 0; - virtual object - makeThrowable - (Thread* t, Machine::Type type, object message = 0, object trace = 0, - object cause = 0) = 0; - virtual void boot(Thread* t) = 0; @@ -1709,19 +1709,6 @@ setObjectClass(Thread*, object o, object value) | (reinterpret_cast(cast(o, 0)) & (~PointerMask))); } -inline Thread* -startThread(Thread* t, object javaThread) -{ - Thread* p = t->m->processor->makeThread(t->m, javaThread, t); - - if (t->m->system->success(t->m->system->start(&(p->runnable)))) { - return p; - } else { - p->exit(); - return 0; - } -} - inline const char* findProperty(Machine* m, const char* name) { @@ -1759,6 +1746,69 @@ runJavaThread(Thread* t) t->m->classpath->runThread(t); } +inline bool +startThread(Thread* t, Thread* p) +{ + return t->m->system->success(t->m->system->start(&(p->runnable))); +} + +inline Thread* +startThread(Thread* t, object javaThread) +{ + Thread* p = t->m->processor->makeThread(t->m, javaThread, t); + + if (startThread(t, p)) { + return p; + } else { + return 0; + } +} + +inline void +registerDaemon(Thread* t) +{ + ACQUIRE_RAW(t, t->m->stateLock); + + atomicOr(&(t->flags), Thread::DaemonFlag); + + ++ t->m->daemonCount; + + t->m->stateLock->notifyAll(t->systemThread); +} + +inline void +checkDaemon(Thread* t) +{ + if (threadDaemon(t, t->javaThread)) { + registerDaemon(t); + } +} + +inline Thread* +attachThread(Machine* m, bool daemon) +{ + Thread* t = m->processor->makeThread(m, 0, m->rootThread); + m->system->attach(&(t->runnable)); + + enter(t, Thread::ActiveState); + + t->javaThread = m->classpath->makeThread(t, m->rootThread); + + threadPeer(t, t->javaThread) = reinterpret_cast(t); + + if (daemon) { + threadDaemon(t, t->javaThread) = true; + + registerDaemon(t); + } + + enter(t, Thread::IdleState); + + m->localThread->set(t); + + return t; +} + inline object& root(Thread* t, Machine::Root root) { @@ -2237,6 +2287,28 @@ findMethodInClass(Thread* t, object class_, object name, object spec) (t, classMethodTable(t, class_), name, spec, methodName, methodSpec); } +inline object +makeThrowable +(Thread* t, Machine::Type type, object message = 0, object trace = 0, + object cause = 0) +{ + PROTECT(t, message); + PROTECT(t, trace); + PROTECT(t, cause); + + if (trace == 0) { + trace = makeTrace(t); + } + + object result = make(t, vm::type(t, type)); + + set(t, result, ThrowableMessage, message); + set(t, result, ThrowableTrace, trace); + set(t, result, ThrowableCause, cause); + + return result; +} + object findInHierarchyOrNull(Thread* t, object class_, object name, object spec, object (*find)(Thread*, object, object, object)); @@ -2254,7 +2326,7 @@ findInHierarchy(Thread* t, object class_, object name, object spec, &byteArrayBody(t, name, 0), &byteArrayBody(t, spec, 0), &byteArrayBody(t, className(t, class_), 0)); - t->exception = t->m->classpath->makeThrowable(t, errorType, message); + t->exception = makeThrowable(t, errorType, message); } return o; @@ -2707,12 +2779,10 @@ wait(Thread* t, object o, int64_t milliseconds) bool interrupted = monitorWait(t, m, milliseconds); if (interrupted) { - t->exception = t->m->classpath->makeThrowable - (t, Machine::InterruptedExceptionType); + t->exception = makeThrowable(t, Machine::InterruptedExceptionType); } } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::IllegalMonitorStateExceptionType); + t->exception = makeThrowable(t, Machine::IllegalMonitorStateExceptionType); } if (DebugMonitors) { @@ -2741,8 +2811,7 @@ notify(Thread* t, object o) if (m and monitorOwner(t, m) == t) { monitorNotify(t, m); } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::IllegalMonitorStateExceptionType); + t->exception = makeThrowable(t, Machine::IllegalMonitorStateExceptionType); } } @@ -2759,8 +2828,7 @@ notifyAll(Thread* t, object o) if (m and monitorOwner(t, m) == t) { monitorNotifyAll(t, m); } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::IllegalMonitorStateExceptionType); + t->exception = makeThrowable(t, Machine::IllegalMonitorStateExceptionType); } } @@ -2803,34 +2871,6 @@ interrupt(Thread* t, Thread* target) } } -inline void -setDaemon(Thread* t, object thread, bool daemon) -{ - ACQUIRE_RAW(t, t->m->stateLock); - - if ((threadDaemon(t, thread) != 0) != daemon) { - threadDaemon(t, thread) = daemon; - - Thread* p = reinterpret_cast(threadPeer(t, thread)); - if (p) { - if (daemon) { - atomicOr(&(p->flags), Thread::DaemonFlag); - } else { - atomicAnd(&(p->flags), ~Thread::DaemonFlag); - } - } - - if (daemon) { - ++ t->m->daemonCount; - } else { - expect(t, t->m->daemonCount); - -- t->m->daemonCount; - } - - t->m->stateLock->notifyAll(t->systemThread); - } -} - object intern(Thread* t, object s); @@ -3157,8 +3197,7 @@ primitiveClass(Thread* t, char name) case 'V': return type(t, Machine::JvoidType); case 'Z': return type(t, Machine::JbooleanType); default: - t->exception = t->m->classpath->makeThrowable - (t, Machine::IllegalArgumentExceptionType); + t->exception = makeThrowable(t, Machine::IllegalArgumentExceptionType); return 0; } } diff --git a/src/process.cpp b/src/process.cpp index cab5fb8b4f..00edbe66b7 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -243,7 +243,7 @@ resolveNative(Thread* t, object method) &byteArrayBody(t, methodName(t, method), 0), &byteArrayBody(t, methodSpec(t, method), 0)); - t->exception = t->m->classpath->makeThrowable + t->exception = makeThrowable (t, Machine::UnsatisfiedLinkErrorType, message); return; }