start0()是jvm用c++实现的native方法,负责将java线程对象映射为操作系统原生线程:java层调用start()→jni绑定到jvm_startthread→jvm创建javathread→os::create_thread()调用pthread_create()等系统api。

start0() 不是 Java 写的,是 JVM 的“操作系统入口”
当你写 thread.start(),真正干活的不是 Java 代码,而是 JVM 里用 C++ 实现的一整套线程创建逻辑。start0() 是一个 native 方法,它不包含 Java 字节码,只有一行声明:private native void start0();。它的作用很明确:把 Java 层的线程对象,翻译成操作系统能理解的指令,让 OS 真正分配一个内核级线程。
调用链路从 Java 到 Linux 线程,一共四层
这条链不是凭空跳转的,而是逐层委托、严格对应的:
-
Java 层:Thread.java 中的
start()调用start0() -
JNI 绑定层:在
openjdk/src/share/native/java/lang/Thread.c里,start0被映射为JVM_StartThread函数 -
JVM 核心层:
hotspot/src/share/vm/prims/jvm.cpp中的JVM_StartThread创建JavaThread对象,并调用其prepare()和start() -
运行时与 OS 层:
hotspot/src/share/vm/runtime/thread.cpp最终调用os::create_thread()—— 这个函数在 Linux 下就是pthread_create()的封装
为什么必须走这一整套?绕不开 native
Java 是跨平台语言,但线程创建不是标准 API,而是操作系统专属能力。Windows 用 CreateThread,Linux 用 pthread_create,macOS 用 pthread_create 变体。JVM 用 C++ 把这些差异收口,对外只暴露统一的 start0()。你无法用纯 Java 实现线程启动,就像无法用 Java 直接申请物理内存页一样——这是 JVM 的职责边界。
怎么验证这个链路?三个轻量方法
不需要编译 OpenJDK,也能确认底层走向:
- 查 OpenJDK 官方源码仓库,在
src/hotspot/share/vm/prims/jvm.cpp搜索JVM_StartThread,能看到完整实现 - 用
jstack查看运行中线程,会显示java.lang.Thread.State: RUNNABLE,而底层对应的是 OS 级线程 ID(可用ps -T -p <pid></pid>验证) - 加 JVM 参数
-XX:+PrintGCDetails -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -Xlog:os+thread=debug,启动时可看到线程注册和 OS 映射日志
别把 start0() 当黑盒,它本质是“JavaThread → pthread”的翻译器
每次 start0() 被调用,JVM 就做三件事:分配 JavaThread 结构体、初始化栈空间、调用 OS 接口拉起原生线程。之后该原生线程会自动执行 JVM 注册的入口函数(比如 thread_entry),再由 JVM 控制权交还给你的 run() 方法。整个过程没有魔法,只有清晰的跨语言协作契约。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











