专栏首页向治洪深入理解Java之jvm启动流程

深入理解Java之jvm启动流程

概述

当我们写一个Java类,并重写Main方法,程序就能运行起来。main方法的背后,程序为什么能运行,jvm究竟做了什么处理?要理解这些,就需要了解jvm的设计原理以及启动的流程。

虚拟机的启动入口位于share/tools/launcher/java.c的main方法,整个流程分为如下几个步骤: 1、配置JVM装载环境 2、解析虚拟机参数 3、设置线程栈大小 4、执行Java main方法

jvm启动流程分析

配置JVM装载环境

Java代码执行时需要一个JVM环境,JVM环境的创建包括两部分:JVM.dll文件的查找和装载。

JVM.dll文件查找

我们来看一段Jre通过环境的路径和系统版本寻找jvm.cfg文件的代码。

说明: 1、GetJREPath()查找当前JRE环境的所在路径; 2、ReadKnownVms()读取JRE路径\lib\ARCH(CPU构架)\JVM.cfg文件,其中ARCH(CPU构架)通过GetArch方法获取,在window下有三种情况:amd64、ia64和i386; 3、CheckJvmType确定当前JVM类型,先判断是否通过-J、-XXaltjvm=或-J-XXaltjvm=参数指定,如果没有,则读取JVM.cfg文件中配置的第一个类型; 4、GetJVMPath根据上一步确定的JVM类型,找到对应的JVM.dll文件;

JVM.dll文件的装载

调用JVM.dll文件中定义的函数初始化虚拟机中的函数。

JVM.dll文件的装载:

1、LoadLibrary方法装载JVM.dll动态连接库; 2、把JVM.dll文件中定义的函数JNI_CreateJavaVM和JNI_GetDefaultJavaVMInitArgs绑定到InvocationFunctions变量的CreateJavaVM和GetDefaultJavaVMInitArgs函数指针变量上;

虚拟机参数解析

装载完JVM环境之后,需要对启动参数进行解析,其实在装载JVM环境的过程中已经解析了部分参数,该过程通过ParseArguments方法实现,并调用AddOption方法将解析完成的参数保存到JavaVMOption中,JavaVMOption结构实现如下:

AddOption代码:

AddOption核心就是对-Xss参数进行特殊处理,并设置threadStackSize,因为参数格式比较特殊,其它是key/value键值对,它是-Xss512的格式。后续Arguments类会对JavaVMOption数据进行再次处理,并验证参数的合理性。

参数处理

Arguments::parse_each_vm_init_arg方法负责处理经过解析过的JavaVMOption数据,部分实现如下:

这里列出了JavaVMOption三个常用的参数: 1、-Xmn:设置新生代的大小NewSize和MaxNewSize; 2、-Xms:设置堆的初始值InitialHeapSize,也是堆的最小值; 3、-Xmx:设置堆的最大值MaxHeapSize;

参数验证

Arguments::check_gc_consistency方法负责验证虚拟机启动参数中配置GC的合理性,实现如下:

1、如果参数为-XX:+UseSerialGC -XX:+UseParallelGC,由于UseSerialGC和UseParallelGC不能兼容,JVM启动时会抛出错误信息; 2、如果参数为-XX:+UseConcMarkSweepGC -XX:+UseParNewGC,其中UseConcMarkSweepGC和UseParNewGC可以兼容,JVM可以正常启动;

设置线程栈大小

如果启动参数未设置-Xss,即threadStackSize为0,则调用InvocationFunctions的GetDefaultJavaVMInitArgs方法获取JavaVM的初始化参数,即调用JVM.dll函数JNI_GetDefaultJavaVMInitArgs,定义在share\vm\prims\jni.cpp,实现如下:

ThreadStackSize定义在globals.hpp中,根据当前系统类型,加载对应的配置文件,所以在不同的系统中,ThreadStackSize的默认值也不同。

执行main方法

线程栈大小确定后,通过ContinueInNewThread方法创建新线程,并执行JavaMain函数,JavaMain函数的大概流程如下:

1、新建JVM实例

InitializeJVM方法调用InvocationFunctions的CreateJavaVM方法,即调用JVM.dll函数JNI_CreateJavaVM,新建一个JVM实例,该过程比较复杂,会在后续文章进行分析。

2、加载主类的class

Java运行方式有两种:jar方式和class方式。

jar方式:

1、调用GetMainClassName方法找到META-INF/MANIFEST.MF文件指定的Main-Class的主类名; 2、调用LoadClass方法加载主类的class文件;

class方式:

1、调用NewPlatformString方法创建类名的String对象; 2、调用LoadClass方法加载主类的class文件;

3,查找main方法

通过GetStaticMethodID方法查找指定方法名的静态方法,实现如下:

最终调用JVM.dll函数jni_GetStaticMethodID实现。

其中get_method_id方法根据类文件对应的instanceKlass对象查找指定方法。

4、执行main方法

1、重新创建参数数组; 2、其中mainID是main方法的入口地址,CallStaticVoidMethod方法最终调用JVM.dll中的jni_CallStaticVoidMethodV函数。

最终通过JavaCalls::call执行main方法,到此Jvm调用main方法启动类的完整流程就讲完了。

本文参与 腾讯云自媒体分享计划 ,欢迎热爱写作的你一起参与!
本文分享自作者个人站点/博客:https://blog.csdn.net/xiangzhihong8复制
如有侵权,请联系 yunjia_community@tencent.com 删除。
登录 后参与评论
0 条评论

相关文章

  • Flutter启动流程的深入解析

    Flutter是怎么启动起来的,是在Android的Activity的启动之后吗?等等这样的问题,在这个文章中将被解答。

    砸漏
  • 深入理解Activity启动流程和AMS框架(一)

    Android应用程序的载体是APK文件,它是一个组件和资源的容器。APK文件和我们常见可执行文件的区别是:每个可执行文件在一个单独的进程中,但是APK文件可能...

    open
  • 深入理解Activity启动流程和AMS框架(二)

    ActivityThread中的成员变量mActivities中保存了所有ActivityClientRecord对象,该类中重要的成员变量如下:

    open
  • 深入理解Activity启动流程和AMS框架(三)

    Intent中定义了一个标志FLAGACTIVITYNEW_TASK,在startActivity的Intent参数中加入该标志就能开启一个新的Task。但是,...

    open
  • 深入理解JVM(③)线程与Java的线程

    我们都知道,线程是比进程更轻量级的调度执行单位,线程的引入,可以把一个进程的资源分配和执行调度分开,各个线程既可以共享进程资源调度(内存地址、文件I/O等),又...

    纪莫
  • 深入理解Java之JVM堆内存分配

    Java堆是被所有线程共享的一块内存区域,所有对象和数组都在堆上进行内存分配。为了进行高效的垃圾回收,虚拟机把堆内存划分成新生代、老年代和永久代(1.8中无永久...

    xiangzhihong
  • 深入理解Java之JVM堆内存分配

    Java堆是被所有线程共享的一块内存区域,所有对象和数组都在堆上进行内存分配。为了进行高效的垃圾回收,虚拟机把堆内存划分成新生代、老年代和永久代(1.8中无永久...

    xiangzhihong
  • 001. 深入JVM学习—Java运行流程

    山海散人
  • 深入理解Activity启动模式之launchMode

    Android每个Application都是由若干个四大组件组成的。每个页面都是一个Activity,当需要打开相应页面(Activity)时系统会创建他们的实...

    静默加载
  • 深入理解Java之线程池

    转载自:http://www.importnew.com/19011.html#comment-653957

    天涯泪小武
  • Jvm(jdk8)源码分析1-java命令启动流程详解

    技巅
  • JVM-深入理解Java虚拟机 原

    1.虚拟机字节码执行引擎 1)物理机和虚拟机的执行引擎区别 物理机:直接建立在处理器、硬件、指令集、操作系统层面上 虚拟机:执行引擎是自己实现的,可以自行...

    秋日芒草
  • 深入理解JVM(③)Java的模块化

    JDK9引入的Java模块化系统(Java Platform Module System ,JPMS)是 对Java技术的一次重要升级,除了像之前JAR包那样充...

    纪莫
  • 深入理解JVM(③)Java的锁优化

    从JDK5到JDK6HotSpot虚拟机开发团队花费了大量的资源实现了各种锁优化技术,如适应性自旋(Adaptive Spinning)、锁消除(Lock El...

    纪莫
  • 深入理解JVM(③)Java的锁优化

    从JDK5到JDK6HotSpot虚拟机开发团队花费了大量的资源实现了各种锁优化技术,如适应性自旋(Adaptive Spinning)、锁消除(Lock El...

    纪莫
  • java(5)-深入理解虚拟机JVM

    在Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟的机器。这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口。编译...

    黄规速
  • 深入理解JVM原理之编译openjdk7

    Java虚拟机种类很多例如:HotSpot 丶 JRockit 丶 J9等 我们一般用的就是HotSpot,如果我们电脑上装了JDK,可以运行java -ver...

    用户1215919
  • 【深入理解Java原理】 JVM 内存区域

    Java 内存区域分成,堆,方法区,虚拟机栈,本地方法栈,程序计数器 (直接内存不是JVM内存的一部分但是有时候会导致OutOFMemory)

    王小明_HIT

扫码关注云+社区

领取腾讯云代金券