坦白说,很不想写,一是感觉自己写不清楚,另外就是有点懒。最后还是打算写完这个去江边跑步,算今天任务完成回家了。好了,废话不多说,开始整体。
刚学习java的人肯定都听过jvm,jdk,jre,也晓得java牛逼的点是一次编译,到处执行。那java为什么能这么牛逼,一次编译,导出执行,其实奥秘就在jvm这里。
jvm全称Java Virtual Machine(java 虚拟机),也就是说你运行java程序的时候,其实是有个一个虚拟的电脑把你的程序编程当前实体电脑能执行的编码,然后输出正确的结果。
既然是虚拟机,稍微有点计算机常识的人肯定会想到,程序计数器、堆、栈之类的,实际确实有这么回事。我们还是从helloworld说起吧。
class HelloWorld{
public static void main(String[] args){
System.out.print(" HELLO WORLD");
}
}
很简单的代码,我现在写了这样一个HelloWorld.java文件,众所周知,源文件是不能直接运行了,为了让了能输出"HELLO WORLD"的字符串,必须要编译。因此我们就调用javac来编译,这些东东都在jdk提供了命令,这也是我们为啥要安装jdk
编译完我们就有HelloWorld.class的文件,这个是java的一个中间文件,如果要运行,就需要java HelloWorld命令就打印出我们想要的结果,奥秘就在这里了。
运行java HelloWorld打印的时候,我们就启动了虚拟机。虚拟机要做的事情如下:
图1 Java程序执行流程
简答来说就是:
1.加载HelloWorld.class文件
2.在内存中new 块区域来存放HelloWorld对象(这里已经完成机器码的转换)
3.调用main入口函数,执行print打印结果。(程序=数据结构+算法,忽然想到的,希望后续看有帮助)
其中jvm独立承担了java程序的内存分配、指令计数和栈的管理等等吧,这样才能让能实现 一次执行多次加载。
如图1所示,我们把HelloWorld.class文件加载到jvm运行是内存后,运行虚拟机程序执行。虚拟机一般会寻找你的jar包或者class文件的入口程序,即main函数,启动一个线程来执行。
那jvm的体系结构官方说法是这样的:
图2 jvm体系结构 jdk7
运行数据区域中有写是线程共享的,有些是虚拟机程序进程的。
其中方法区和堆是虚拟机进程。
java栈、PC记数器和本地方法栈是线程独有的,跟着线程消亡而消亡。
class文件加载器,是加载class文件
执行引擎,是将Java的字节指令转为机器指令。