运行Java -jar somefile.jar时发生了什么(二)
(6)Java.c中的LoadMainClass
位置jdk/src/share/bin/java.c
该方法负责载入main函数所在的类。
该方法首先载入sun.launcher.LauncherHelper类,然后调用该类的checkAndLoadMain去找到main函数所在的类,相关代码例如以下。
jclass cls = GetLauncherHelperClass(env);//这个函数载入了sun.launcher.LauncherHelper类
NULL_CHECK0(cls);
if (JLI_IsTraceLauncher()) {
start = CounterGet();
}
NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls,//找到方法id
"checkAndLoadMain",
"(ZILjava/lang/String;)Ljava/lang/Class;")); str = NewPlatformString(env, name);
result = (*env)->CallStaticObjectMethod(env, cls, mid, USE_STDERR, mode, str);//调用这个静态方法
(7)LauncherHelper.java中的checkAndLoadMain
位置:jdk/src/share/bin/classes/sun/launcher/LauncherHelper.java
Java代码比較直观。我就直接写凝视了
</pre><p><pre name="code" class="java"> public static Class<? > checkAndLoadMain(boolean printToStderr,
int mode,
String what) {
initOutput(printToStderr);
// mode决定是直接传入的主类还是jar文件。即区分java -jar xxx.jar 还是 java xxx.class
String cn = null;
switch (mode) {
case LM_CLASS:
cn = what;
break;
case LM_JAR:
cn = getMainClassFromJar(what);//这个函数的原理是抽取jar中的mainfest文件得到其主类
break;
default:
// should never happen
throw new InternalError("" + mode + ": Unknown launch mode");
}
cn = cn.replace('/', '.');
Class<?> mainClass = null;
try {
mainClass = scloader.loadClass(cn);//使用scloader载入,怎样载入水比較深。这里就不展开说了。 } catch (NoClassDefFoundError | ClassNotFoundException cnfe) {
if (System.getProperty("os.name", "").contains("OS X")
&& Normalizer.isNormalized(cn, Normalizer.Form.NFD)) {
try {
// On Mac OS X since all names with diacretic symbols are given as decomposed it
// is possible that main class name comes incorrectly from the command line
// and we have to re-compose it
mainClass = scloader.loadClass(Normalizer.normalize(cn, Normalizer.Form.NFC));
} catch (NoClassDefFoundError | ClassNotFoundException cnfe1) {
abort(cnfe, "java.launcher.cls.error1", cn);
}
} else {
abort(cnfe, "java.launcher.cls.error1", cn);
}
}
// set to mainClass
appClass = mainClass; /*
* Check if FXHelper can launch it using the FX launcher. In an FX app,
* the main class may or may not have a main method, so do this before
* validating the main class.
*/
if (mainClass.equals(FXHelper.class) ||
FXHelper.doesExtendFXApplication(mainClass)) {
// Will abort() if there are problems with the FX runtime
FXHelper.setFXLaunchParameters(what, mode);
return FXHelper.class;
} validateMainClass(mainClass);//这里对主类有效性即可了验证,代码附在后面。
return mainClass;
}
接下来给出了验证主类是否有效的代码。
static void validateMainClass(Class<?> mainClass) {
Method mainMethod;
try {
mainMethod = mainClass.getMethod("main", String[].class);//看看是否存在例如以下签名的方法 main(String[] argvs)
} catch (NoSuchMethodException nsme) {
// invalid main or not FX application, abort with an error
abort(null, "java.launcher.cls.error4", mainClass.getName(),
FXHelper.JAVAFX_APPLICATION_CLASS_NAME);
return; // Avoid compiler issues
}
int mod = mainMethod.getModifiers();//取得限定符
if (!Modifier.isStatic(mod)) {//假设不是static的则报错
abort(null, "java.launcher.cls.error2", "static",
mainMethod.getDeclaringClass().getName());
}
if (mainMethod.getReturnType() != java.lang.Void.TYPE) {
abort(null, "java.launcher.cls.error3",//假设不是void的也报错
mainMethod.getDeclaringClass().getName());
}
}
二、总结
这两篇博客主要分析了运行java命令详细会发生一些什么事情,通过阅读代码能够了解到配置的环境变量怎样起作用。jvm何时初始化。以及主类载入及验证过程。
本片博客起码还有下面几点没有深入的分析到:
jvm怎样初始化。
env结构和vm结构的关系及实现。
scloader怎么作用。
LauncherHelper怎样载入。
这些问题也许会在后面的博客进行分析。
运行Java -jar somefile.jar时发生了什么(二)的更多相关文章
- 运行java可执行jar包
导出与导入:如果要用别的项目的类, 把对方类export出成jar包(多个类的集合),然后复制到自己项目路径下然后添加至构建路径,jar包右键buildpath/addtobuildpath.expo ...
- dos窗口运行java文件需要jar依赖
执行java文件时候,有些里面依赖了java之外的jar,这是识别不到的,运行java命令的时候,带上jar路径: java -cp .;jar路径(加上jar名字) java文件名 例:java ...
- 跑Java -jar somefile.jar时会发生什么(一个)
最近阅读JVM源代码.一些想法写Blog分享.于是,他开了这么一个新课题. 第一篇文章取名字的时候让我很困惑,我代码的阅读是从Launcher開始入手的,也就是Java.exe(假设是windows平 ...
- java项目打成jar包时引用了第三方jar,此时我们该如何解决呢
Web项目做多了,反而对单纯的java项目陌生了,今天我们在开发项目的过程中,碰到一个这样的需求:需要将java项目放到linux系统上跑起来,当然这个javaSE项目是带main方法的.我们知道在I ...
- Linux环境下执行java -jar xxx.jar命令如何让springboot项目在后台运行
段落引用> 由于springboot内置了tomcat容器,我们通常会把项目打成jar或者war后直接使用java -jar xxx.jar命令去运行程序,但是当前ssh窗口被锁定或者按下ctr ...
- shell脚本运行java程序jar
在UBuntu上部署项目的时候,我们往往通过一段shell来启动程序,甚至是通过crontab定时任务来定时的调用java程序,但是很奇怪的一个问题就是,比如我写了一个如下的shell脚本: #!/b ...
- Linux后台运行java的jar包
Linux 运行jar包命令如下: 方式一 特点:当前ssh窗口被锁定,可按CTRL + C打断程序运行,或直接关闭窗口,程序退出 那如何让窗口不锁定? 方式二 java -jar shareniu. ...
- 【乱码】运行java -jar xx.jar存到hbase里的数据乱码
程序在Eclipse里运行没有问题,但是打成jar包之后写入hbase里的数据会有乱码,ES里正常 经过测试,运行命令里加上-Dfile.encoding=utf-8 就可以正常写入,但是cmd命令里 ...
- 关于 maven 打包直接运行的 fat jar (uber jar) 时需要包含本地文件系统第三方 jar 文件的问题
关于maven打包fat jar (uber jar) 时需要包含本地文件系统第三方jar文件的问题,今天折腾了一整天.最后还是用了spring boot来做.下面是几篇关于打包的有参考价值的文章,以 ...
随机推荐
- acm练习-day1
描述现在,有一行括号序列,请你检查这行括号是否配对.输入第一行输入一个数N(0<N<=100),表示有N组测试数据.后面的N行输入多组输入数据,每组输入数据都是一个字符串S(S的长度小于1 ...
- 北大ACM(POJ1015-Jury Compromise)
Question:http://poj.org/problem?id=1015 问题点:DP. Memory: 1352K Time: 94MS Language: C++ Result: Accep ...
- Crash (computing)
In computing, a crash (or system crash) occurs when a computer program, such as a software applicati ...
- Java 8 和 Java 9部分区别
Java 8 和 Java 9中 concurrent 包有了一些改变, 本文对这些改变做了汇总.Java 8 中 Concurrent package的改变java.util.concurrent中 ...
- day15-模块的基础及导入
目录 模块 什么是模块 使用模块 import 循环导入问题 解决方案一 解决方案二 模块的搜索路径 Python文件的两种用途 包 导入包内包 导入包内包的模块 绝对导入与相对导入 绝对导入 相对导 ...
- CAD得到布局名
js代码如下: var database = mxOcx.GetDatabase(); var sRet = null; //返回数据库中的布局字典 var spLayoutDictionary = ...
- 梦想CAD控件系统变量说明
这里介绍一些常用系统变量有String.double.long.McGePoint3d等类型,其中有部分系统变量是随图纸保存,再次打开时就会读取图纸中的系统变量,有些系统变量不随图纸保存,其作用来控制 ...
- 梦想MxWeb3D,三维CAD协同设计平台 2019.04.09更新
SDK开发包下载地址: http://www.mxdraw.com/ndetail_10140.html 在线演示网址: http://www.mxdraw.com:3000/ 1. 增加上传dwg ...
- 01Microsoft SQL Server
Microsoft SQL Server Microsoft SQL Server 是Microsoft 公司推出的关系型数据库管理系统.具有使用方便可伸缩性好与相关软件集成程度高等优点,可跨越膝上型 ...
- BZOJ2657: [Zjoi2012]旅游(journey) (树形DP)
题意:一个三角划分的凸多边形 画一条对角线 穿过最多的三角形 题解:把每一个三角形看作一个点 如果某条边是两个三角形的公共边 那么就把这两个三角形连边 然后问题就转化为求树上的最长链了 就当求个直径就 ...