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: &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