【Java虚拟机】第一章、Java虚拟机是如何产生的

先不讲java虚拟机,我们从最最基本的出发。

当我开始学习java之初,老是听我老师吹牛逼说java能跨平台,如何如何厉害,我一直有疑问,java可以跨平台,别的就不行?很惭愧,现在才正式开始总结一下:

1.、java是如何做到跨平台的,为什么有了JDK,JRE就能跨平台

2、为什么tomcat能在各个平台运行,靠的是啥,为啥运行之后访问的东西都是一样的,不会有linux和window的区别?

以下以windows平台为例

【解决第一个问题:为什么有了JDK、JRE,就能跨平台】

首先我们先了解下进程的概念:

        第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。----来自百度百科

        第二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时(操作系统执行之),它才能成为一个活动的实体,我们称其为进程

为什么要先了解进程的概念,在我的理解来看java虚拟机就是一个进程

然后我们在看问题,JDK和JRE分别是什么作用:最简单的理解,JDK就是个工具包,JRE全称Java runtime enviroment,java运行时环境。

       jre既然是java运行环境,那么环境是怎么产生的呢?

表面上看,执行java.exe就产生了JVM,其实可以分为四步:

    1.执行代码时(如JAVATEST),操作系统会查找java.exe程序,具体执行过程,先执行方法CreateExcutionEnvironment(java_md.c),在这个方法中,根据GetApplicationHome查找你的java.exe所在目录,然后截取目录c:/program/java/jdk/bin,并查找java.dll是否在此目录中,如果存在就把c:/program/java/jdk作为jre路径,如果不存在则判断c:/program/java/jdk/jre/bin/java.dll是否存在,如果存在则把c:/program/java/jdk/jre作为路径,如果不存在,则调用GetPublicJREHome查HKEY_LOCAL_MACHINE/Software/JavaSoft/JavaRuntimeEnvironment/“当前JRE版本号”/JavaHome的路径为jre路径。

      其次,我们要找到相应的jvm.cfg,确定要使用哪个jvm.dll,因为在我们的jdk目录中jre/bin/server和jre/bin/client都有JVM.dll文件,所以我们从JRE路径+/lib+/ARCH(CPU构架)+/JVM.cfg找到配置文件。CPU架构ARCH是在java_md.c中getArch方法判断的,里面只有两个分支,一个是64为的,一个是X86。找到jvm.cfg之后,我们就可以确定要使用哪个jvm.dll。

    2.找到jvm.dll之后,就开始载入JVM.dll,里面是C代码(dll为动态链接库文件:含义为程序共享执行特殊任务所必需的代码和资源。白话:调用系统资源,调用系统API),具体载入方法为通过LoadJavaVM(具体实现在java_md.c,line365,里面包含了createJavaVM,以及获取jvm初始化参数的方法)。装入工作很简单就是调用WindowsAPI函数:LoadLibary装载jvm.dll动态链接库,然后吧jvm.dll中的导出函数jni_createjavavm和jni_getDefaultjavavminitargs挂接到invocationFunctions变量的CraeteJavaVm和GetDefaultJavaVMInitargs函数指针变量上。

    3.初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例。如果jvm要调用内部代码,需要JNIEnv(包含了本地window函数的接口),jvm如果要调用的话,需要在C或者C++代码中申明。

    4.调用JNIEnv实例装载并处理class类。这里必须要说一下,怎么运行java程序,一种是class运行,一种是jar。java.exe调用GetMainClassName函数,该函数先获得JNIEnv实例然后调用java类,

Java.util.jar.JarFileJNIEnv中方法getManifest()并从返回的Manifest对象中取getAttributes("Main-Class")的值即jar包中文件:META-INF/MANIFEST.MF指定的Main-Class的主类名作为运行的主类。之后main函数会调用Java.c中LoadClass方法装载该主类(使用JNIEnv实例的FindClass)。main函数直接调用Java.c中LoadClass方法装载该类。如果是执行class方法。main函数直接调用Java.c中LoadClass方法装载该类。

然后main函数调用JNIEnv实例的GetStaticMethodID方法查找装载的class主类中

“publicstaticvoidmain(String[]args)”方法,并判断该方法是否为public方法,然后调用JNIEnv实例的

CallStaticVoidMethod方法调用该Java类的main方法。
--------------------- 
参考:https://blog.csdn.net/wyt4455/article/details/8717328 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值