跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

零基础教程:手把手带你理清 start() 方法底层的 JVM 本地 C++ 调用

start() 方法触发 JVM 创建真正的 OS 线程,而非直接调用 run();其流程为:Java 层校验状态并设为 RUNNABLE,JVM 通过 JVM_StartThread → JavaThread::start_thread() → os::create_thread()(Linux 下即 pthread_create)创建线程,再由 C++ thread_entry 初始化后调用 Java 的 run()。 java 中的
start()
方法看似简单,但背后牵扯的是 java 层、jvm 运行时、线程调度和本地操作系统的一整套协作机制。它不是直接调用
run()
,而是触发 jvm 启动一个真正的 os 线程——这个过程在 hotspot jvm 中由 c++ 实现,不暴露给 java 开发者,但理清它能帮你真正理解“多线程为何不能靠反复调用 run() 来实现”。 start() 不是执行 run(),而是注册并唤醒一个新线程 调用
Thread.start()
时,Java 层只是做了几件事:检查线程状态(必须是 NEW)、设置线程为 RUNNABLE 状态、把线程对象加入 JVM 的线程列表。真正的线程创建动作发生在 JVM 的本地方法
JVM_StartThread
中——这是个 JNI 函数,由 HotSpot 的
thread.cpp
实现。 Java 层的
start()
最终会跳转到
JVM_StartThread
(定义在
src/hotspot/share/prims/jvm.cpp
) 该函数内部调用
JavaThread::start_thread()
,后者封装了
os::create_thread()
os::create_thread()
是平台相关实现,Linux 下本质是
pthread_create
调用 底层 C++ 线程入口不是 run(),而是 thread_entry JVM 不会让 OS 线程直接执行你写的
run()
方法。它先启动一个统一的 C++ 入口函数
thread_entry
(位于
src/hotspot/share/runtime/thread.cpp
),再由这个函数完成 Java 栈初始化、JNI 环境绑定,最后才调用 Java 的
run()
。
thread_entry
接收的是
JavaThread*
指针,不是 Java 对象 它会调用
thread->run()
(注意:这是 C++ 的
JavaThread::run()
,不是 Java 的
Runnable.run()
) 这个 C++
run()
再通过 JNI 调用目标线程对象的
run()
方法(即你重写的那个) 为什么重复调用 start() 会抛 IllegalThreadStateException? 因为 JVM 在 C++ 层维护了线程的生命周期状态机。一旦
os::create_thread()
成功返回,线程状态就从 NEW 变为 RUNNABLE;如果此时再调
start()
,
JVM_StartThread
会检测到状态非法,直接返回失败,Java 层捕获后抛出异常。 状态存储在
JavaThread
对象的
_thread_state
字段中(枚举值如
NEW
、
RUNNABLE
、
TERMINATED
) 这个字段在
os::create_thread()
前被设为
RUNNABLE
,创建失败则回滚;成功后不可逆 所以哪怕线程已执行完
run()
进入
TERMINATED
,也不能再次
start()
—— JVM 不允许复用线程对象 调试建议:想看 C++ 层发生了什么? 不需要编译整个 JVM。你可以: C知道 CSDN推出的一款AI技术问答工具 下载 立即学习 “ C++免费学习笔记(深入) ”; 下载 OpenJDK 源码(推荐 jdk8u 或 jdk17u),定位到
src/hotspot/share/prims/jvm.cpp
查
JVM_StartThread
用
hsdis
+
java -XX:+PrintAssembly
观察 JIT 编译后的本地代码(适合进阶) 在 Linux 下用
strace -e trace=clone,pthread_create
运行简单多线程程序,看到底层系统调用 加 JVM 参数
-XX:+PrintGCDetails -XX:+PrintGCDateStamps
配合线程 dump(
jstack
)对比状态变化 理解
start()
的本地调用链,不是为了写 JNI,而是建立对“Java 线程即 OS 线程”这一事实的肌肉记忆。它解释了为何线程开销大、为何有数量限制、为何要谨慎使用线程池——这些都不是语言规范写的,而是藏在那几行 C++ 里。

相关文章