当前位置: 首页 > news >正文

OpenJDK8源码系列01-JVM生命周期源码概览

1. 引言

JVM(Java Virtual Machine)是 Java 程序的运行基石。理解 JVM 的生命周期,即从启动到销毁的完整过程,是深入掌握 Java 运行时机制的第一步。本文将从 OpenJDK8 源码出发,概述在linux系统JVM 的启动、初始化、执行与销毁四个核心阶段的调用链,帮助读者建立对 JVM 整体架构的宏观认知。

2. JVM 启动入口

JVM 的启动入口位于src/share/bin/main.c文件中的main()函数。

// src/share/bin/main.cintmain(intargc,char**argv){...returnJLI_Launch(margc,margv,sizeof(const_jargs)/sizeof(char*),const_jargs,sizeof(const_appclasspath)/sizeof(char*),const_appclasspath,FULL_VERSION,DOT_VERSION,(const_progname!=NULL)?const_progname:*margv,(const_launcher!=NULL)?const_launcher:*margv,(const_jargs!=NULL)?JNI_TRUE:JNI_FALSE,const_cpwildcard,const_javaw,const_ergo_class);}

进入main函数,JVM进程开始运行。该函数相对简单,调用了JLI_Launch函数

// src/share/bin/java.c/* * Entry point. */intJLI_Launch(intargc,char**argv,/* main argc, argc */intjargc,constchar**jargv,/* java args */intappclassc,constchar**appclassv,/* app classpath */constchar*fullversion,/* full version defined */constchar*dotversion,/* dot version defined */constchar*pname,/* program name */constchar*lname,/* launcher name */jboolean javaargs,/* JAVA_ARGS */jboolean cpwildcard,/* classpath wildcard*/jboolean javaw,/* windows-only javaw */jint ergo/* ergonomics class policy */){...CreateExecutionEnvironment(&argc,&argv,jrepath,sizeof(jrepath),jvmpath,sizeof(jvmpath),jvmcfg,sizeof(jvmcfg));ifn.CreateJavaVM=0;ifn.GetDefaultJavaVMInitArgs=0;...if(!LoadJavaVM(jvmpath,&ifn)){return(6);}...returnJVMInit(&ifn,threadStackSize,argc,argv,mode,what,ret);}

JLI_Launch函数需要重点关注的是调用了CreateExecutionEnvironment、LoadJavaVM和JVMInit等函数。
CreateExecutionEnvironment函数创建运行环境
LoadJavaVM函数主要是加载JVM共享链接库libvjm.so,将函数指针ifn->CreateJavaVM指向JNI_CreateJavaVM,ifn->GetDefaultJavaVMInitArgs指向JNI_GetDefaultJavaVMInitArgs,ifn->GetCreatedJavaVMs指向JNI_GetCreatedJavaVMs。

// src/solaris/bin/java_md_solinux.cintJVMInit(InvocationFunctions*ifn,jlong threadStackSize,intargc,char**argv,intmode,char*what,intret){...returnContinueInNewThread(ifn,threadStackSize,argc,argv,mode,what,ret);}

JVMInit调用了ContinueInNewThread函数去开启新线程。

// src/share/bin/java.cintContinueInNewThread(InvocationFunctions*ifn,jlong threadStackSize,intargc,char**argv,intmode,char*what,intret){...rslt=ContinueInNewThread0(JavaMain,threadStackSize,(void*)&args);return(ret!=0)?ret:rslt;}}

ContinueInNewThread函数调用了ContinueInNewThread0函数去开启新线程。
如果成功创建新线程,由新线程调用JavaMain函数。到目前为止,在linux内核角度来看,linux内核已经为该JVM进程创建了两个TASK_STRUCT.。一个是之前main函数所在的TASK_STRUCT暂且叫它A,一个是新线程所在的TASK_STRUCT暂且叫它B。A关联的线程会一直等待B关联的线程运行完再继续运行。
如果创建新线程失败,则由原有的线程调用JavaMain函数。到目前为止,在linux内核角度来看,linux内核已经为该JVM进程创建了一个TASK_STRUCT.

// src/share/bin/java.cintJNICALLJavaMain(void*_args){...if(!InitializeJVM(&vm,&env,&ifn)){JLI_ReportErrorMessage(JVM_ERROR1);exit(1);}...mainClass=LoadMainClass(env,mode,what);..mainID=(*env)->GetStaticMethodID(env,mainClass,"main","([Ljava/lang/String;)V");...mainArgs=CreateApplicationArgs(env,argv,argc);...(*env)->CallStaticVoidMethod(env,mainClass,mainID,mainArgs);..LEAVE();}

JavaMain函数中调用了InitializeJVM、LoadMainClass、(*env)->GetStaticMethodID、CreateApplicationArgs、 (*env)->CallStaticVoidMethod等关键函数和宏LEAVE().
InitializeJVM函数极为重要,做了很多事情,初始化ClassLoader,创建了堆并进行初始化,创建垃圾收集器和相应的垃圾收集策略,后面在详解InitializeJVM再详细展开。
LoadMainClass函数找到并加载JAVA应用的Main Class.
(*env)->GetStaticMethodID获取JAVA应用Main Class的main方法ID。
CreateApplicationArgs函数创建JAVA应用Main Class main方法的参数。
(*env)->CallStaticVoidMethod函数开始调用Java应用Main Class的main方法,这里开始运行JAVA程序代码。
宏LEAVE()在JAVA应用程序执行完后对JVM进行销毁。

至此,JVM生命周期源码概览结束。

http://www.gsyq.cn/news/1418245.html

相关文章:

  • 用Wireshark抓包,一步步拆解IPv6 SLAAC自动配置的完整流程(附报文详解)
  • 别再手动封装SRAM了!用Memory Wrapper工具一键搞定接口、ECC和时序调整
  • 工业EtherCAT主站在RT-Linux上的DC同步实现与WKC错误优化
  • 2026 年 5 月基金从业备考避坑:免费题库与电子版软件实测 - 讲清楚了
  • Bambu Studio国际化开发实战:从零到一打造多语言3D打印软件
  • Linux无线打印避坑指南:爱普生L3255通过TCP/IP连接成功打印的完整配置流程
  • 上海软件开发服务商那么多,企业数字化转型期该如何精准选择
  • Layuimini企业级后台架构最佳实践:高可用可扩展前端解决方案
  • GitHub加速插件:告别龟速访问,体验极速下载
  • 别再手动diff了!Ubuntu 22.04上Beyond Compare 4保姆级安装与汉化配置指南
  • 观察Taotoken平台在高峰时段的API服务稳定性表现
  • 2026年至今,河北地区建筑资质延期办理流程咨询公司深度解析 - 2026年企业资讯
  • 2026年如何甄选可靠的新风软连接定做厂家?系统梳理与品牌解析 - 2026年企业资讯
  • 从摇杆到漫步:手把手用Unity 2021.3 + OpenXR配置VR自由移动(支持Quest 2)
  • Unity项目优化实战:用Editor脚本一键批量修改图片MaxSize和压缩格式(附完整代码)
  • 移动硬盘盘符突然从E变F?别慌,用Windows磁盘管理5分钟改回来
  • 别再让xray扫出你的源码!手把手教你排查与修复Webpack项目中的sourcemap泄露
  • 【原创解锁】叫叫识字 趣味启蒙识字 动画学字超有趣
  • 彻底告别自动更新!Win11系统下Chrome离线安装与永久禁用GoogleUpdate服务指南
  • TTS 推理速度为什么这么慢:序列长度问题与扩散模型的计算瓶颈
  • 用Python+NumPy手把手实现一个马尔可夫链预测模型(附完整代码)
  • 从Simulink到虚幻引擎:一个自动驾驶仿真小白的踩坑与配置全记录
  • 不只是好看:聊聊MydockFinder如何提升我的Windows工作效率
  • 阴阳师自动化脚本终极指南:一站式智能游戏辅助实战手册
  • 避坑指南:Unity ShaderGraph做刮刮乐效果,为什么你的笔刷边缘有锯齿?
  • 10分钟玩转LLM API调用+Prompt设计,零基础也能快速落地AI应用
  • 用8050三极管和FR107二极管,我复刻了一个简易ZVS振荡电路(附完整电路图)
  • 终极RPG Maker解密工具:3步轻松提取加密游戏资源
  • 保姆级教程:在Ubuntu 20.04上用GStreamer 1.16.2源码编译并启动你的第一个RTSP服务器
  • Unity InputSystem虚拟摇杆实战:从基础配置到三种高级模式(固定/跟随/灵活)