JDK-8269466 : Factor out the common code for initializing and starting internal VM JavaThreads
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 18
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2021-06-28
  • Updated: 2021-07-08
  • Resolved: 2021-07-02
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 18
18 b05Fixed
Related Reports
Relates :  
Relates :  
Description
Following threads are all created by main thread during VM init, so we have a valid current Thread in the VM and Java.

AttachListener:
  - uses system_thread_group
  - JavaCalls::construct_new_instance
    - allocates Thread
    - calls Thread(ThreadGroup tg, String name)
  - call ThreadGroup.add(Thread t)
ThreadsLock {
  - new JavaThread(entry)
  - java_lang_Thread::set_thread(thread_oop(), thread);
 ** NO java_lang_Thread::set_priority **
  - java_lang_Thread::set_daemon(thread_oop());
  - thread->set_threadObj(thread_oop());
  - Threads::add(thread);
  - Thread::start(thread);
}

ServiceThread:
MonitorDeflationThread:
  - uses system_thread_group
  - JavaCalls::construct_new_instance
    - allocates Thread
    - calls Thread(ThreadGroup tg, String name)
ThreadsLock {
  - new XXXThread(entry)
  - java_lang_Thread::set_thread(thread_oop(), thread);
  - java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
  - java_lang_Thread::set_daemon(thread_oop());
  - thread->set_threadObj(thread_oop());
  - Threads::add(thread);
  - Thread::start(thread);
}
  ** NO CALL to group.add(t) as these are hidden system threads.

NotificationThread:
SignalThread:
  - uses system_thread_group
  - JavaCalls::construct_new_instance
    - allocates Thread
    - calls Thread(ThreadGroup tg, String name)
  - call ThreadGroup.add(Thread t)  **** only difference from previous
ThreadsLock {
  - new XXXThread(entry)
  - java_lang_Thread::set_thread(thread_oop(), thread);
  - java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
  - java_lang_Thread::set_daemon(thread_oop());
  - thread->set_threadObj(thread_oop());
  - Threads::add(thread);
  - Thread::start(thread);
}

JfrRecorderThread:
 - calls up to JFR Java code to create j.l.Thread
 - uses system thread group
ThreadsLock {
  - new JavaThread(entry)
  - java_lang_Thread::set_thread(thread_oop(), thread);
  - java_lang_Thread::set_priority(thread_oop(), NormPriority); ** different
  - java_lang_Thread::set_daemon(thread_oop());
  - thread->set_threadObj(thread_oop());
  - Threads::add(thread);
}
  - Thread::start(thread);

JvmtiAgentThread:
 - j.l.Thread already exists and is passed in
ThreadsLock {
  - new JvmtiAgentThread(...)
  - java_lang_Thread::set_thread(thread_oop(), thread);
  - java_lang_Thread::set_priority(thread_oop(), priority); ** different
  - java_lang_Thread::set_daemon(thread_oop());
  - thread->set_threadObj(thread_oop());
  - Threads::add(thread);
  - Thread::start(thread);
}

CompilerThreads:
 - j.l.Thread handling is a bit specialized
 - code when holding ThreadsLock is basically the same, but priority is more complex
    - calls os::set_native_priority directly


Differences:
- ThreadGroup.add
  - Without a call to add() threads will not be listed in this TG and it is invisible.
  - Some threads must be visible i.e. NotificationThread and SignalThread
- Priority value - most nearMaxPriority but JFR is Norm and CompilerThreads are special
  - Note: we only set the priority field of the j.l.Thread, we don't call os::set_priority
  - Some threads call os::set_priority at the start of the thread-entry method
  - As a separate RFE we should fix this to that we do call os::set_priority consistently either before starting the target or when it runs
- Exception handling for Java calls can differ
  - attachlistener uses special logic
- Use of vm_exit_during_initialization
  - not for JfrRecorderThread, or JVMTI agent thread

Otherwise logic while holding Threads_lock is common and can be factored out:
- create XXXThread outside of ThreadsLock and pass in as JavaThread*
  - so error handling is done at call site not in common code

j.l.Thread creation can also be factored out. Then the two parts combined for maximum reuse.

The basic pattern would be:

- obj = create threadObj
- thread = create XXXThread
- handle allocation failure
- startInternalThread(thread, obj)

This RFE will not look at the java.lang.Thread object creation to keep things simpler.
Comments
Changeset: 4107dcf6 Author: David Holmes <dholmes@openjdk.org> Date: 2021-07-02 04:29:47 +0000 URL: https://git.openjdk.java.net/jdk/commit/4107dcf6ec3fb7fd6eb0e12cdc404a2dee9ccaa1
02-07-2021