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: &apos;java/lang/Thread&apos;
>> fields:
>>    - private &apos;name&apos; &apos;[C&apos; @56
>>    - private &apos;priority&apos; &apos;I&apos; @40
>>    - private &apos;threadQ&apos; &apos;Ljava/lang/Thread;&apos; @60
>>    - private &apos;eetop&apos; &apos;J&apos; @8
>>    - private &apos;single_step&apos; &apos;Z&apos; @48
>>    - private &apos;daemon&apos; &apos;Z&apos; @49
>>    - private &apos;speculative&apos; &apos;Z&apos; @50
>>    - private &apos;stillborn&apos; &apos;Z&apos; @51
>>    - private &apos;target&apos; &apos;Ljava/lang/Runnable;&apos; @64
>>    - private &apos;group&apos; &apos;Ljava/lang/ThreadGroup;&apos; @68
>>    - private &apos;contextClassLoader&apos; 
>> &apos;Ljava/lang/ClassLoader;&apos; @72
>>    - private &apos;inheritedAccessControlContext&apos; 
>> &apos;Ljava/security/AccessControlContext;&apos; @76
>>    - &apos;threadLocals&apos; 
>> &apos;Ljava/lang/ThreadLocal$ThreadLocalMap;&apos; @80
>>    - &apos;inheritableThreadLocals&apos; 
>> &apos;Ljava/lang/ThreadLocal$ThreadLocalMap;&apos; @84
>>    - private &apos;stackSize&apos; &apos;J&apos; @16
>>    - private &apos;nativeParkEventPointer&apos; &apos;J&apos; @24
>>    - private &apos;tid&apos; &apos;J&apos; @32
>>    - private &apos;threadStatus&apos; &apos;I&apos; @44
>>    - volatile &apos;parkBlocker&apos; &apos;Ljava/lang/Object;&apos; @88
>>    - private volatile &apos;blocker&apos; 
>> &apos;Lsun/nio/ch/Interruptible;&apos; @92
>>    - private &apos;blockerLock&apos; &apos;Ljava/lang/Object;&apos; @96
>>    - private &apos;stopBeforeStart&apos; &apos;Z&apos; @52
>>    - private &apos;throwableFromStop&apos; 
>> &apos;Ljava/lang/Throwable;&apos; @100
>>    - private volatile &apos;uncaughtExceptionHandler&apos; 
>> &apos;Ljava/lang/Thread$UncaughtExceptionHandler;&apos; @104
>> mainThreadGroup: java.lang.ThreadGroup
>>  - klass: &apos;java/lang/ThreadGroup&apos;
>> fields:
>>    - &apos;parent&apos; &apos;Ljava/lang/ThreadGroup;&apos; @28
>>    - &apos;name&apos; &apos;Ljava/lang/String;&apos; @32
>>    - &apos;maxPriority&apos; &apos;I&apos; @8
>>    - &apos;destroyed&apos; &apos;Z&apos; @24
>>    - &apos;daemon&apos; &apos;Z&apos; @25
>>    - &apos;vmAllowSuspension&apos; &apos;Z&apos; @26
>>    - &apos;nUnstartedThreads&apos; &apos;I&apos; @12
>>    - &apos;nthreads&apos; &apos;I&apos; @16
>>    - &apos;threads&apos; &apos;[Ljava/lang/Thread;&apos; @36
>>    - &apos;ngroups&apos; &apos;I&apos; @20
>>    - &apos;groups&apos; &apos;[Ljava/lang/ThreadGroup;&apos; @40
>> java.lang.String: java.lang.String
>>  - klass: &apos;java/lang/String&apos;
>> string: &quot;Speculative&quot;
>> EARLIER------------------java.lang.NullPointerException
>>  - klass: &apos;java/lang/NullPointerException&apos;
>> fields:
>>    - private transient &apos;backtrace&apos; 
>> &apos;Ljava/lang/Object;&apos; @8
>>    - private &apos;detailMessage&apos; &apos;Ljava/lang/String;&apos; @12
>>    - private &apos;cause&apos; &apos;Ljava/lang/Throwable;&apos; @16
>>    - private &apos;stackTrace&apos; 
>> &apos;[Ljava/lang/StackTraceElement;&apos; @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