Creating a JavaThread and its java.lang.Thread oop
David Holmes - Sun Microsystems
David.Holmes at Sun.COM
Mon Nov 12 16:20:48 PST 2007
And note that the thread doing this construction must itself already be
an attached Java thread - just checking :)
David Holmes
Tom Rodriguez said the following on 13/11/07 09:34 AM:
> 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