Creating a JavaThread and its java.lang.Thread oop
Tom Rodriguez
Thomas.Rodriguez at Sun.COM
Mon Nov 12 15:34:49 PST 2007
Use java_lang_Throwable::print_stack_trace(ex, tty) to get a stack trace for the
exception. I suspect that will answer your question.
By the way, you shouldn't have to declare nullResult to return NULL. CHECK_NULL
is the normal way to do that.
tom
Peter Helfer wrote:
> Ok.. at first it seemed to work... now I get some NullPointerException
> from the Thread.<init>(ThreadGroup, String)-Constructor, as it seems -
> do you see any missing parts ?
>
> The pool datastructure is being created somewhere in the way of
> create_vm(..), as well as some PoolManagerThread to create some new
> threads. This manager is being notfied totally at the end of create_vm()
> to start creating threads; so I assume everything is ready to be used...
>
>
>
> JavaThread* ThreadPool::createThread(ThreadFunction entrypoint, TRAPS){
> // 0) arrange the nullResult
> JavaThread* nullResult = NULL;
>
> // 1) create java.lang.Thread
> klassOop k =
> SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_Thread(),
> true, CHECK_(nullResult));
> instanceKlassHandle klass (THREAD, k);
> instanceHandle thread_oop =
> klass->allocate_instance_handle(CHECK_(nullResult));
>
> // 2) use the main thread_group
> oop thread_group = Universe::main_thread_group();
>
> tty->print("java.lang.Thread object: ");
> thread_oop()->print();
> tty->print("mainThreadGroup: ");
> thread_group->print();
> Handle name = java_lang_String::create_from_str("ThreadPool",
> CHECK_(nullResult));
> tty->print("java.lang.String: ");
> name()->print();
>
> // 3) call <init>(ThreadGroup g, String name) on the java.lang.Thread
> object
> JavaValue result(T_VOID);
> // Thread gets assigned specified name and null target
> JavaCalls::call_special(&result,
> thread_oop,
> klass,
> vmSymbolHandles::object_initializer_name(),
>
> vmSymbolHandles::threadgroup_string_void_signature(),
> thread_group, // Argument 1
> name, // Argument 2
> THREAD);
>
> if (HAS_PENDING_EXCEPTION) {
> oop ex = PENDING_EXCEPTION;
> tty->print("EARLIER------------------");
> ex->print();
> return nullResult;
> }
>
> // 4) now create the JavaThread (this part comes from
> prims/jvm.cpp::JVM_StartThread
> JavaThread *native_thread = NULL;
> //bool throw_illegal_thread_state = false;
> {
> // Ensure that the C++ Thread and OSThread structures aren't
> freed before we operate.
> MutexLocker mu(Threads_lock);
> native_thread = new JavaThread(entrypoint, 0);
> }
> //if (throw_illegal_thread_state) {
> // THROW(vmSymbols::java_lang_IllegalThreadStateException());
> //}
> assert(native_thread != NULL, "Starting null thread?");
> if (native_thread->osthread() == NULL) {
> // No one should hold a reference to the 'native_thread'.
> delete native_thread;
> THROW_MSG_(vmSymbols::java_lang_OutOfMemoryError(), "unable to
> create new native thread", nullResult);
> }
>
> // 5) now save the JavaThread into java.lang.Thread, set the priority,
> and save the
> // java.lang.Thread object into JavaThread as well.
> java_lang_Thread::set_thread(thread_oop(), native_thread);
> java_lang_Thread::set_priority(thread_oop(), NormPriority);
> native_thread->set_threadObj(thread_oop());
>
> // 6) put the new native thread into Threads-list -> is done one
> dequeuing from Pool!
> //{
> // MutexLocker ml(Threads_lock);
> // Threads::add(native_thread);
> //}
>
> // 7) add this thread to the threadGroup as well
> KlassHandle group(THREAD, SystemDictionary::threadGroup_klass());
> Handle threadObj(THREAD, native_thread->threadObj());
>
> JavaCalls::call_special(&result,
> thread_group,
> group,
> vmSymbolHandles::add_method_name(),
> vmSymbolHandles::thread_void_signature(),
> threadObj, // Arg 1
> THREAD);
>
> if (HAS_PENDING_EXCEPTION) {
> oop ex = PENDING_EXCEPTION;
> tty->print("LATER ON------------------");
> ex->print();
> return nullResult;
> }
>
> // 7) finally return the JavaThread created freshly.. the start
> happens elsewhere..
> return native_thread;
>
> }
>
>
> from hotspot.log
> <writer thread='-1210770544'/>
> Notify SpecPoolManager to create threads
> <writer thread='-1380680816'/>
> Start creating the Threads
> SpecMgr: ready/init/max [0, 0, 10]: Adding 10 threads
> java.lang.Thread object: java.lang.Thread
> - klass: 'java/lang/Thread'
> fields:
> - private 'name' '[C' @56
> - private 'priority' 'I' @40
> - private 'threadQ' 'Ljava/lang/Thread;' @60
> - private 'eetop' 'J' @8
> - private 'single_step' 'Z' @48
> - private 'daemon' 'Z' @49
> - private 'speculative' 'Z' @50
> - private 'stillborn' 'Z' @51
> - private 'target' 'Ljava/lang/Runnable;' @64
> - private 'group' 'Ljava/lang/ThreadGroup;' @68
> - private 'contextClassLoader'
> 'Ljava/lang/ClassLoader;' @72
> - private 'inheritedAccessControlContext'
> 'Ljava/security/AccessControlContext;' @76
> - 'threadLocals'
> 'Ljava/lang/ThreadLocal$ThreadLocalMap;' @80
> - 'inheritableThreadLocals'
> 'Ljava/lang/ThreadLocal$ThreadLocalMap;' @84
> - private 'stackSize' 'J' @16
> - private 'nativeParkEventPointer' 'J' @24
> - private 'tid' 'J' @32
> - private 'threadStatus' 'I' @44
> - volatile 'parkBlocker' 'Ljava/lang/Object;' @88
> - private volatile 'blocker'
> 'Lsun/nio/ch/Interruptible;' @92
> - private 'blockerLock' 'Ljava/lang/Object;' @96
> - private 'stopBeforeStart' 'Z' @52
> - private 'throwableFromStop'
> 'Ljava/lang/Throwable;' @100
> - private volatile 'uncaughtExceptionHandler'
> 'Ljava/lang/Thread$UncaughtExceptionHandler;' @104
> mainThreadGroup: java.lang.ThreadGroup
> - klass: 'java/lang/ThreadGroup'
> fields:
> - 'parent' 'Ljava/lang/ThreadGroup;' @28
> - 'name' 'Ljava/lang/String;' @32
> - 'maxPriority' 'I' @8
> - 'destroyed' 'Z' @24
> - 'daemon' 'Z' @25
> - 'vmAllowSuspension' 'Z' @26
> - 'nUnstartedThreads' 'I' @12
> - 'nthreads' 'I' @16
> - 'threads' '[Ljava/lang/Thread;' @36
> - 'ngroups' 'I' @20
> - 'groups' '[Ljava/lang/ThreadGroup;' @40
> java.lang.String: java.lang.String
> - klass: 'java/lang/String'
> string: "Speculative"
> EARLIER------------------java.lang.NullPointerException
> - klass: 'java/lang/NullPointerException'
> fields:
> - private transient 'backtrace'
> 'Ljava/lang/Object;' @8
> - private 'detailMessage' 'Ljava/lang/String;' @12
> - private 'cause' 'Ljava/lang/Throwable;' @16
> - private 'stackTrace'
> '[Ljava/lang/StackTraceElement;' @20
>
>
>
>
>
>
>
>
> 2007/11/6, David Holmes - Sun Microsystems <David.Holmes at sun.com
> <mailto:David.Holmes at sun.com>>:
>
> Peter,
>
> I agree with Tom. Initializing the pool should happen right at the very
> end of create_vm - as that should be the safest place. If you need to
> move it earlier then you can try that one step at a time later.
>
> Your thread creation needs to be a combination, but variation, of
> attach_current_thread and JVM_StartThread. With attach_current_thread
> you have an existing native thread and need to create the JavaThread
> and
> java.lang.Thread. With JVM_StartThread you have a java.lang.Thread and
> need to create the JavaThread and native thread. With your pool you have
> nothing to start with so you need to:
> - create the java.lang.Thread object
> - invoke JVM_StartThread on it (logically not by an actual call) which
> will create the JavaThread and native thread
>
> At present (and I haven't looked too deeply) it seems to me that you
> might be trying to create the new threads all associated with the
> current native thread. Create a raw java.lang.Thread first and then
> "start" it.
>
> BTW if you initialize the pool during VM initialization then you
> shouldn't need to worry about any locking - the main thread is the only
> one that will be interacting with the pool.
>
> Hope this helps.
>
> David Holmes
>
>
>
More information about the hotspot-runtime-dev
mailing list