问题起因:
我注意到再写java程序运行时不会像.exe程序一样出现在windows的任务管理器---进程一栏里面,只能看到javaw.exe。(可以了解一下javaw.exe与java.exe区别)然后经过一系列联想我就到了一个问题:java的.class文件由虚拟机的解释器解释为机器码,这个机器码是给JVM执行的机器码,还是类似于.exe给操作系统执行的机器码。
于是我把这个问题丢到群里面,大家都会有一个观点:这个机器码是给java虚拟机用的。也就是说java代码执行的大致流程为:
假设1:
1.我们手写的.java文件;
2.javac编译后的.class文件;
3.java虚拟机里面的类加载器加载.class文件;
4.字节码解释器将.class文件解释成java虚拟机能执行的机器码(这里面会有类,对象等概览);
5.虚拟机通过执行机器码逻辑和调用系统硬件服务(也就是说java的所有底层硬件服务都由JVM代劳与操作系统交付);
6.程序运行。
这样好像能走通,但是如果机器码是在JVM上执行,那还保留.class文件干嘛,直接机器码和JVM就可以快平台了。而且是这个逻辑的话,想想JVM的实现应该就不是一件很难的事了。
还有我们常常能看到这样的描述,教科书上也是这样的描述:
、
也就是说,java最终产生的机器码是运行于操作系统上的,平台有关的机器码,这与我上面流程的第4步明显不符,再做出第二种假设:
1.我们手写的.java文件;
2.javac编译后的.class文件;
3.java虚拟机里面的类加载器加载.class文件,初始化JVM的堆、栈;
4.java虚拟机里面的解释器将JVM堆、栈里面的数据解释为机器码;
6.操作系统执行机器码,这个过程脱离了;
7.程序运行。可这样,java虚拟机里面的程序计数器有毛用?而且这个流程java程序在windows里面执行时在任务管理栏---进程里面应该会有javaw.exe和xxx.exe两个进程。
后面在网上找了些资料,了解到JVM加载指令是动态链接的,重新思考整理下java代码的执行流程:
假设3:
1.我们手写的.java文件;
2.javac编译后的.class文件;
3.java虚拟机里面的类加载器加载.class文件,初始化JVM的堆、栈、程序计数器等;
4.java虚拟机开始执行加载的.class文件,读取JVM堆、栈的方法指令、变量、参数到JVM的程序计数器准备执行解释;
5.java虚拟机里面的解释器将程序计数器里面的指令、数据解释成操作系统能执行的机器码;
6.操作系统执行机器码,并将结果返回给JVM;
7.程序运行。
以上这些都属于我个人思考,具体是否正确有待验证。可能对于大部分学java的来说这个流程都十分了解,可我最近总是莫名其妙的想些问题,最终还容易陷入死胡同,把自己给弄糊涂了。至于为什么写下来,是觉得这个思考有益,有时候熟悉的事细数起来也并非那么熟悉。准备买本相关的书籍看看,到时再来写结论。可具体是什么时候谁知道呢?10年后?20年后?毕竟现在肚子很饿......