跑Java -jar somefile.jar时会发生什么(一个)
最近阅读JVM源代码。一些想法写Blog分享。于是,他开了这么一个新课题。
第一篇文章取名字的时候让我很困惑,我代码的阅读是从Launcher開始入手的,也就是Java.exe(假设是windows平台的话)相应的相关代码,但我又不能取“JVM启动过程分析”之类的名字,由于从分析主流程的角度来讲还深不到这个层次。所以就暂且起了这么一个奇怪的名字。
这个系列假设能继续下去的话,不加特殊说明,使用的JDK和JVM版本号均为8u20,下载地址来自OpenJDK:http://hg.openjdk.java.net/jdk8u
本人是一个JAVA程序猿,在分析JVM大量C/C++时难免会有不妥当的地方,还希望各位读者指正。
介于时间有涯而代码“无涯”。详细的实现细节不可能面面俱到。仅仅着重分析和看懂大致流程和机制,假设有比較重要的细节遗漏之处。欢迎留言讨论。
在这个系列中,不论什么对源文件位置的描写叙述都使用相对路径。当中jdk/代表放置Jdk源代码的根文件夹,hotspot/代表放置jvm源代码的根文件夹。
一、Launcher代码分析
(1)Main.c中的main
位置:jdk/src/bin/main.c
当我们调用java命令时。首先肯定进入的是C/C++的main函数,就像若干年前我写的那个helloworld一样。
这个main函数位于jdk/src/bin/main.c。在JDK8中是放置在这个位置。在曾经较老版本号是放在JVM相关代码中的。
main.c中差点儿没有实质的逻辑,主要是复制一些參数,处理在windows平台中的一些调用,之后就把各參数传递给JLI_launch进行运行。相关代码在第125行。
return JLI_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);
(2)java.c中的JLI_Launch
位置:jdk/src/bin/java.c
java.c中依据凝视能够大概看出这个函数的各參数含义:
JLI_Launch(int argc, char ** argv, /* main argc, argc */int jargc, const char** jargv, /* java args */int appclassc, const char** appclassv, /* app classpath */const char* fullversion, /* full version defined */const char* dotversion, /* dot version defined */const char* pname, /* program name */const char* lname, /* launcher name */jboolean javaargs, /* JAVA_ARGS */jboolean cpwildcard, /* classpath wildcard*/jboolean javaw, /* windows-only javaw */jint ergo /* ergonomics class policy */
在第236行调用系统函数获取环境变量,给jrepath,jvmpath和jvmcfg赋值。(每一个Java基础教程里设置的环境变量在这里起作用)
CreateExecutionEnvironment(&argc, &argv,jrepath, sizeof(jrepath),jvmpath, sizeof(jvmpath),jvmcfg, sizeof(jvmcfg));
第248行载入jvm.dll这个文件。仅仅是载入文件到内存,并没有运行不论什么操作,同一时候给这个ifn结构体赋值(依据dll抽取函数调用地址赋值),ifn结构体包括三个关键的函数指针。
if (!LoadJavaVM(jvmpath, &ifn)) {return(6);}
Ifn结构例如以下:
typedef struct {CreateJavaVM_t CreateJavaVM;GetDefaultJavaVMInitArgs_t GetDefaultJavaVMInitArgs;GetCreatedJavaVMs_t GetCreatedJavaVMs;
} InvocationFunctions;
依据函数名能够大概猜到,第一个是创建虚拟机。第二个是获取初始參数,第三个是创建非常多虚拟机?(vms代表虚拟机的复数形式?我猜的。。)。
之后又对參数进行了一些额外的处理(包含获取classpath、打印调试信息、加入额外的參数等等)。在299行调用JVMInit初始化虚拟机
return JVMInit(&ifn, threadStackSize, argc, argv, mode, what, ret);
(3)Java.c中的JVMInit
位置:jdk/src/bin/java.c
代码非常少,首先打印一下信息,然后调用ConitueInNewThread函数,从函数名也能够看出,会启用一个新线程建立JVM。
int
JVMInit(InvocationFunctions* ifn, jlong threadStackSize,int argc, char **argv,int mode, char *what, int ret)
{ShowSplashScreen();return ContinueInNewThread(ifn, threadStackSize, argc, argv, mode, what, ret);
}
(4)Java.c中的ContinueInNewThread
位置:jdk/src/bin/java.c
这个函数依旧没做啥东西,就是封装了一下參数,然后委派给ContinueInNewThread0。
而ContinueInNewThread0开启一个新的线程,运行JavaMain函数。
(5)Java.c中的JavaMain
位置:jdk/src/bin/java.c
首先在第371行初始化JVM。而InitializeJVM函数做的工作就是调用ifn->createJavaVM,详细的JVM启动过程水太深因此不在这里进行分析。假设初始化成功,则会给vm对象和env对象赋值,当中env是一个很重要的对象,进行JNI调用的时候会频繁用到。
if (!InitializeJVM(&vm, &env, &ifn)) {JLI_ReportErrorMessage(JVM_ERROR1);exit(1);}
之后检查一下是否传入了Jar文件或者一个类名,假设没有的话就打印一下Usage
之后第439行获取主类,获取主类的方式挺有意思的。在后面会进行分析。
接着看看是否抛异常,假设抛异常就直接退出了。
mainClass = LoadMainClass(env, mode, what);CHECK_EXCEPTION_NULL_LEAVE(mainClass);
随后针对JavaFX载入一下东西(假设须要的话),然后获取main这种方法的ID,组合參数,并Invoke。水到渠成。
当中每一步都检查是否有异常抛出。
mainID = (*env)->GetStaticMethodID(env, mainClass, "main","([Ljava/lang/String;)V");CHECK_EXCEPTION_NULL_LEAVE(mainID);/* Build platform specific argument array */mainArgs = CreateApplicationArgs(env, argv, argc);CHECK_EXCEPTION_NULL_LEAVE(mainArgs);/* Invoke main method. */(*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);/** The launcher's exit code (in the absence of calls to* System.exit) will be non-zero if main threw an exception.*/ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
(未完待续)
版权声明:本文博客原创文章。博客,未经同意,不得转载。
跑Java -jar somefile.jar时会发生什么(一个)相关推荐
- java中什么表示打印_在java中打印对象时会发生什么
您不需要调试器就能知道发生了什么. System.out是PrintStream类型. PrintStream.println(Object)的javadoc说: Prints an Object a ...
- 教你打包Java程序,jar转exe随处可跑
本文出自One Coder博客,转载请务必注明出处:http://www.coderli.com/archives/runnablejar-to-exe/ 发现很多人问如何把Jar转成exe程序.可能 ...
- java ear war_[转] 基于Java的打包jar、war、ear包的作用与区别详解
以最终客户的角度来看,JAR文件就是一种封装,他们不需要知道jar文件中有多少个.class文件,每个文件中的功能与作用,同样可以得到他们希望的结果.除jar以外对于J2EE来说还有war和ear.区 ...
- 理论+实践轻松掌握nohup java -jar xxxx.jar /dev/null 21 意义
前言 相信大家经常能在shell脚本中发现>/dev/null 2>&1这样的语句.以前的我并没有去深入地理解这段命令的作用,照搬照用,直到上周我将这段命令不小心写成了2>& ...
- 打包部署后无法读取jar包里的文件(实测可行,Java中读取jar包中的文件)
打包部署后无法读取jar包里的文件 Java中读取jar包中的文件 linux中无法读取jar包中的内容(windows可以的!),如何解决 一.背景 项目中免不了需要读取文件,如果文件用绝对路径读取 ...
- 一步一步教你将java代码打成jar包用bat批处理命令运行
1.背景 前不久接到一个朋友的请求,让我帮他做个小程序处理一些工作上的事情,好歹作为java开发工程师,这点忙还是要帮的.不过马上遇到了一个问题,平时我们都是用IDEA或者eclipse运行的代码, ...
- java中的jar文件
官方英文介绍******************************************************************************************* In ...
- 由java:local_policy.jar和US_export_policy.jar引发的“血案”
起因:今天项目上线,上线后监测日志,发现由异常,开始查找问题 ,进而引发了"血案" 线上日志报错如下:Illegal key size 画外音:看到线上项目出现问题心里慌的一批 赶 ...
- java基于RXTXcomm.jar的串口通信
java基于RXTXcomm.jar的串口通信 RXTX的下载及配置 mfz-rxtx-2.2-20081207-win-x64 下载地址:http://download.csdn.net ...
最新文章
- .NET平台开源项目速览(11)KwCombinatorics排列组合使用案例(1)
- 灰色简约三级CSS下拉菜单代码
- quratz数据存储
- LeetCode 2055. 蜡烛之间的盘子(前缀和)
- android adapter hierarchy
- 转 从20秒到0.5秒:一个使用Rust语言来优化Python性能的案例
- Java NIO概述(1)
- linux远程拷贝快捷键远程,linux命令scp远程拷贝
- java使用谷歌验证码google captcha
- 架构师应该具备什么技能
- 2022.10.25 固体物理
- 中国剩余定理(孙子定理)(模板)
- 制作京东快报页面html,京东快报.html
- 《超越对手-大项目售前售后的30种实战技巧》读书心得
- 八年级英语下册计算机教学总结,初中信息技术教学工作总结
- 二维burgers方程_用格子Boltzmann方法研究二维Burgers方程
- 怎么做网站?网站用什么服务器好?
- 【嵌入式】51单片机+1602+dht11显示温湿度
- 金仓数据库 KingbaseES SQL 语言参考手册 (11. SQL语句:ABORT 到 ALTER INDEX)
- 【一】数字图像的常见概念