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