start() 方法触发JVM与操作系统协同机制,使Java线程成为内核可调度实体:校验NEW状态、创建JavaThread、注册全局列表、调用pthread_create生成LWP,实现1:1映射。

Java 的 start() 方法不是简单地执行一段代码,而是触发一整套 JVM 与操作系统协同工作的机制,最终让一个 Java 线程真正成为内核可调度的实体。
start() 触发 JNI 层线程创建流程
调用 t.start() 后,JVM 执行本地方法 start0(),该方法通过 JNI 绑定到 HotSpot 的 JVM_StartThread 函数。这个函数不直接创建线程,而是协调完成以下关键动作:
- 校验线程状态:仅当线程处于 NEW 状态时才允许启动,否则抛出
IllegalThreadStateException - 分配
JavaThread对象,初始化其内部结构(如栈内存、GC 栈帧、TLS 存储等) - 将线程注册进 JVM 全局线程列表(
Threads::add()),使其能被 GC、安全点、调试器识别 - 调用平台相关函数
os::start_thread(),在 Linux 上即进入os_linux.cpp中的os::create_thread()
Linux 上 pthread_create 是真正的调度入口
os::create_thread() 在 Linux 中调用 pthread_create() 创建原生线程,这是 Java 线程获得 OS 级调度能力的关键一步:
- 传入的启动函数是
java_start(不是用户写的run()),它负责切换到 Java 栈、初始化线程局部环境,再调用run() - 第四个参数
arg指向 JVM 内部的Thread*,供java_start使用 - 栈大小由
-Xss控制,默认 1MB,JVM 将其转为pthread_attr_setstacksize - 线程属性设为
PTHREAD_CREATE_JOINABLE,以支持join()等同步操作
1:1 映射可验证:每个 Java 线程 = 一个 Linux LWP
Java 线程不是虚拟机模拟出来的,而是真实绑定到内核轻量级进程(LWP)。这种一对一关系可通过多种方式实锤:
立即学习“Java免费学习笔记(深入)”;
-
ps -T -p [pid]显示的 TID 列,数量与成功调用start()的次数严格一致 -
/proc/[pid]/task/目录下每个子目录名就是一个内核分配的唯一 TID,对应一个task_struct -
strace -f -e trace=clone -p [pid]可捕获每次start()触发的clone(CLONE_VM | CLONE_FS | CLONE_THREAD)系统调用 - 主线程的 TGID(线程组 ID)等于进程 PID,其余线程的 TGID 也相同,但各自拥有独立 TID
run() 和 start() 的本质区别在此处彻底体现
run() 只是一个普通 Java 方法,直接调用它不会触发任何底层线程创建逻辑;而 start() 是唯一能激活整个映射链路的入口:
- 没有
start(),JVM 不会调用pthread_create(),也不会为线程分配osthread结构体 - 缺少
osthread,JVM 就无法管理该线程的生命周期(如interrupt()、isAlive())、无法扫描其栈上对象(影响 GC)、Thread.currentThread()也无法返回它 - 即使你用 JNI 自己调用
pthread_create(),只要没走 JVM 的os::create_thread()流程,这个线程对 JVM 来说就是“不存在”的


















