Creating a JavaThread and its java.lang.Thread oop

Peter Helfer peter.helfer.java at gmail.com
Mon Nov 12 09:01:31 PST 2007


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.Threadobject
  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>:
>
> 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
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/attachments/20071112/3f950665/attachment.html 


More information about the hotspot-runtime-dev mailing list