Unveiling Java Thread Mechanics: From JVM States to Native Startup
This article explains how Java threads map to OS kernel threads, details the Thread.State lifecycle, shows how to create threads by extending Thread or implementing Runnable, and walks through the JNI mechanism and HotSpot source code that drives thread startup and execution.
Basic Concepts
Java threads are mapped to operating‑system kernel threads, so the JVM relies on the OS to manage them. In Linux, threads and processes share the same internal structure; a process has its own address space while threads within the same process share resources.
Simple note: this article is based on OpenJDK 1.8.
Thread States
Each state transition and the corresponding method are illustrated in the diagram below. The
Thread.Stateenum defines the following states:
<code>public enum State {<br/> // New, not yet started<br/> NEW,<br/><br/> // Runnable, may be waiting for OS resources<br/> RUNNABLE,<br/><br/> // Blocked, waiting for a monitor lock<br/> BLOCKED,<br/><br/> // Waiting for another thread to perform a specific action<br/> WAITING,<br/><br/> // Timed waiting, can set a maximum wait time<br/> TIMED_WAITING,<br/><br/> // Terminated<br/> TERMINATED;<br/>}</code>Thread Creation
Extend the Thread class:
<code>class PrimeThread extends Thread {<br/> long minPrime;<br/> PrimeThread(long minPrime) { this.minPrime = minPrime; }<br/><br/> public void run() {<br/> // compute primes larger than minPrime<br/> ...<br/> }<br/>}<br/><br/>PrimeThread p = new PrimeThread(143);<br/>p.start();</code>Implement the Runnable interface (generally recommended):
<code>class PrimeRun implements Runnable {<br/> long minPrime;<br/> PrimeRun(long minPrime) { this.minPrime = minPrime; }<br/><br/> public void run() {<br/> // compute primes larger than minPrime<br/> ...<br/> }<br/>}<br/><br/>PrimeRun p = new PrimeRun(143);<br/>new Thread(p).start();</code>HotSpot Source Code
JNI Mechanism
JNI (Java Native Interface) provides a set of APIs that enable Java to communicate with native languages such as C and C++. It is useful for reusing existing C libraries, interacting with hardware or the operating system, and improving performance, but it introduces two major drawbacks:
Platform dependence – native code must be compiled for each target OS.
Safety concerns – misuse can crash the JVM; native methods should be confined to a few classes to reduce coupling.
Typical usage scenario: when a legacy C library needs to be accessed from Java without rewriting it in pure Java.
Startup Process
The thread startup flow is illustrated below.
Thread Startup
After a
Threadinstance is created, calling
start()triggers the native method
start0(), which registers native methods and creates an OS thread.
<code>public synchronized void start() {<br/> // Check thread state<br/> if (threadStatus != 0) throw new IllegalThreadStateException();<br/><br/> // Add to thread group<br/> group.add(this);<br/><br/> boolean started = false;<br/> try {<br/> // Start the native thread<br/> start0();<br/> started = true;<br/> } finally {<br/> try {<br/> if (!started) {<br/> group.threadStartFailed(this);<br/> }<br/> } catch (Throwable ignore) { /* ignore */ }<br/> }<br/>}<br/><br/>private native void start0();</code>The native
start0()method is defined in HotSpot as
Java_java_lang_Thread_start0:
<code>JNIEXPORT void JNICALL Java_java_lang_Thread_start0(JNIEnv *, jobject);</code>During JVM initialization,
Thread.registerNatives()registers this and other native methods:
<code>static JNINativeMethod methods[] = {<br/> {"start0", "()V", (void *)&JVM_StartThread},<br/> {"stop0", "()V", (void *)&JVM_StopThread},<br/> // ... other native methods ...<br/>};<br/><br/>JNIEXPORT void JNICALL Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls) {<br/> env->RegisterNatives(cls, methods, ARRAY_LENGTH(methods));<br/>}</code> JVM_StartThread(implemented in
src/share/vm/prims/jvm.cpp) creates a
JavaThreadobject, allocates a native OS thread via
os::create_thread, and finally calls
Thread::startto mark the thread as runnable.
<code>JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))<br/> JavaThread *native_thread = NULL;<br/> // ... create JavaThread and OS thread ...<br/> Thread::start(native_thread);<br/>JVM_END</code>The
JavaThreadconstructor invokes
os::create_thread, which on Linux uses
pthread_createto launch the native thread:
<code>bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {<br/> OSThread* osthread = new OSThread(NULL, NULL);<br/> thread->set_osthread(osthread);<br/> pthread_t tid;<br/> int ret = pthread_create(&tid, &attr, (void*(*)(void*)) java_start, thread);<br/> return true;<br/>}</code>The entry point
java_startsimply calls the Java thread’s
run()method:
<code>static void* java_start(Thread* thread) {<br/> thread->run();<br/> return 0;<br/>}</code>Inside the HotSpot VM,
JavaThread::run()eventually invokes
thread_main_inner, which calls the user‑provided entry point (the
run()method of the target
Runnableor the overridden
Thread.run()).
<code>void JavaThread::thread_main_inner() {<br/> if (!this->has_pending_exception() && !java_lang_Thread::is_stillborn(this->threadObj())) {<br/> this->entry_point()(this, this);<br/> }<br/> // cleanup and exit<br/> this->exit(false);<br/> delete this;<br/>}</code>The Java
Thread.run()implementation simply delegates to the associated
Runnableif present:
<code>public void run() {<br/> if (target != null) {<br/> target.run();<br/> }<br/>}</code>References
https://www.jb51.net/article/216231.htm
https://blog.csdn.net/u013928208/article/details/108051796
https://www.cnblogs.com/whhjava/p/9916626.html
https://www.runoob.com/w3cnote/jni-getting-started-tutorials.html
https://developer.51cto.com/art/202011/632936.htm
https://blog.csdn.net/weixin_34384681/article/details/90660510
https://blog.csdn.net/weixin_30267697/article/details/95994035
https://zhuanlan.zhihu.com/p/33830504
Ops Development Stories
Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.