最近阅读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时会发生什么(一个)相关推荐

  1. java中什么表示打印_在java中打印对象时会发生什么

    您不需要调试器就能知道发生了什么. System.out是PrintStream类型. PrintStream.println(Object)的javadoc说: Prints an Object a ...

  2. 教你打包Java程序,jar转exe随处可跑

    本文出自One Coder博客,转载请务必注明出处:http://www.coderli.com/archives/runnablejar-to-exe/ 发现很多人问如何把Jar转成exe程序.可能 ...

  3. java ear war_[转] 基于Java的打包jar、war、ear包的作用与区别详解

    以最终客户的角度来看,JAR文件就是一种封装,他们不需要知道jar文件中有多少个.class文件,每个文件中的功能与作用,同样可以得到他们希望的结果.除jar以外对于J2EE来说还有war和ear.区 ...

  4. 理论+实践轻松掌握nohup java -jar xxxx.jar /dev/null 21 意义

    前言 相信大家经常能在shell脚本中发现>/dev/null 2>&1这样的语句.以前的我并没有去深入地理解这段命令的作用,照搬照用,直到上周我将这段命令不小心写成了2>& ...

  5. 打包部署后无法读取jar包里的文件(实测可行,Java中读取jar包中的文件)

    打包部署后无法读取jar包里的文件 Java中读取jar包中的文件 linux中无法读取jar包中的内容(windows可以的!),如何解决 一.背景 项目中免不了需要读取文件,如果文件用绝对路径读取 ...

  6. 一步一步教你将java代码打成jar包用bat批处理命令运行

    1.背景 前不久接到一个朋友的请求,让我帮他做个小程序处理一些工作上的事情,好歹作为java开发工程师,这点忙还是要帮的.不过马上遇到了一个问题,平时我们都是用IDEA或者eclipse运行的代码, ...

  7. java中的jar文件

    官方英文介绍******************************************************************************************* In ...

  8. 由java:local_policy.jar和US_export_policy.jar引发的“血案”

    起因:今天项目上线,上线后监测日志,发现由异常,开始查找问题 ,进而引发了"血案" 线上日志报错如下:Illegal key size 画外音:看到线上项目出现问题心里慌的一批 赶 ...

  9. java基于RXTXcomm.jar的串口通信

    java基于RXTXcomm.jar的串口通信 RXTX的下载及配置 mfz-rxtx-2.2-20081207-win-x64       下载地址:http://download.csdn.net ...

最新文章

  1. .NET平台开源项目速览(11)KwCombinatorics排列组合使用案例(1)
  2. 灰色简约三级CSS下拉菜单代码
  3. quratz数据存储
  4. LeetCode 2055. 蜡烛之间的盘子(前缀和)
  5. android adapter hierarchy
  6. 转 从20秒到0.5秒:一个使用Rust语言来优化Python性能的案例
  7. Java NIO概述(1)
  8. linux远程拷贝快捷键远程,linux命令scp远程拷贝
  9. java使用谷歌验证码google captcha
  10. 架构师应该具备什么技能
  11. 2022.10.25 固体物理
  12. 中国剩余定理(孙子定理)(模板)
  13. 制作京东快报页面html,京东快报.html
  14. 《超越对手-大项目售前售后的30种实战技巧》读书心得
  15. 八年级英语下册计算机教学总结,初中信息技术教学工作总结
  16. 二维burgers方程_用格子Boltzmann方法研究二维Burgers方程
  17. 怎么做网站?网站用什么服务器好?
  18. 【嵌入式】51单片机+1602+dht11显示温湿度
  19. 金仓数据库 KingbaseES SQL 语言参考手册 (11. SQL语句:ABORT 到 ALTER INDEX)
  20. 【一】数字图像的常见概念

热门文章

  1. python学习_19
  2. mysql给root开启远程访问权限,修改root密码
  3. 思科——单臂路由与DHCP的结合
  4. spring-session源码解读 sesion
  5. 【ASM学习】普通数据库向ASM实例的迁移(二)
  6. 查杀linux线程指令
  7. Ubuntu10下MySQL搭建Amoeba_读写分离
  8. 不支持mac os x软件虚拟化。要运行mac os x,您需要主机VMware workstation支持硬
  9. 定义对象或数组直接量时不同引擎对多余逗号的处理
  10. 【心情】为什么发英文版免责声明?