1.什么是Java虚拟机
我们知道Java程序必须在虚拟机上运行。那么虚拟机到底是什么呢?
虚拟机是一种抽象化的计算机,通过再实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。JVM屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码,就可以在多种平台上不加修改地运行。
一般我们不需要知道虚拟机的运行原理,只要专注写Java代码就可以了,这也正是虚拟机之所以存在的原因,屏蔽低层操作系统平台的不同并且减少基于原生语言开发的复杂性,使java这么语言能够跨各种平台。
2.从进程角度解释JVM
可以这样理解,当它在运行的收,它就是一个操作系统中的进程实例,当它没有在运行时(作为可执行文件存放于文件系统中),可以把它叫做程序。
3.比较C语言和Java语言说明JVM
C语言:HelloWorld.c
#include <stdio.h>
#include <stdlib.h>
int main(void) {
printf("hello world\n");
return 0;
}
编译:
gcc HelloWorld.c -o HelloWorld
运行: ./HelloWorld
gcc编译器编译后的文件直接就是可被操作系统识别的二进制可执行文件,当我们在命令行中敲下./HelloWorld时,会直接创建一个进程,并且将可执行文件加载到进程的地址空间中,执行文件中的指令。
Java语言:HelloWorld.java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("HelloWorld");
}
}
编译:
javac HelloWorld.java
编译结果:HelloWorld.class HelloWorld.java
运行:java HelloWorld
运行java版的HelloWorld时,敲入的命令并不是./HelloWorld.class。因为class文件并不是可以直接被操作系统识别的二进制可执行文件。我们敲入的是java命令。这个命令说明,我们首先启动的是一个叫做java的程序,这个java程序在运行起来以后就是一个JVM进程实例。
上面的命令执行流程是这样的:
java命令首先启动虚拟机进程,虚拟机进程成功启动后,读取参数"HelloWorld",把他作为初始类加载到内存,对这个类进行初始化和动态链接,然后从这个类的main方法开始执行。也就是说我们的.class文件不是直接被系统加载后直接在cpu上执行的,而是被一个叫做虚拟机的进程托管的。首先必须虚拟机进程启动就绪,然后由虚拟机中的类加载器加载必要的class文件,包括jdk中的基础类(如String和Object等),然后由虚拟机进程解释class字节码指令,把这些字节码指令翻译成本机cpu能够识别的指令,才能在cpu上运行。
从这个层面上来看,在执行一个所谓的java程序的时候,真真正正在执行的是一个叫做Java虚拟机的进程,而不是我们写的一个个的class文件。这个叫虚拟机的进程处理一些底层的操作,比如内存的分配和释放等等。我们编写的class文件只是虚拟机进程执行时需要的“原料”。这些“原料”在运行时被加载到虚拟机中,被虚拟机解释执行,以控制虚拟机实现我们java代码中所定义的一些相对高层的操作,比如创建一个文件等,可以将class文件中的信息看做对虚拟机的控制信息,也就是一种虚拟指令。
4.JVM体系结构简介
我们编译之后的class文件是作为Java虚拟机的原料被输入到Java虚拟机的内部的,那么具体由谁来做这一部分工作呢?其实在Java虚拟机内部,有一个叫做类加载器的子系统,这个子系统用来在运行时根据需要加载类。在Java虚拟机执行过程中,只有他需要一个类的时候,才会调用类加载器来加载这个类,并不会再开始运行时加载所有的类。就像一个人,只有饿的时候才去吃饭,而不是一次把一年的饭都吃到肚子里。一般来说,虚拟机加载类的时机,在第一次使用一个新的类的时候。
由虚拟机加载的类,被加载到Java虚拟机内存中之后,虚拟机会读取并执行它里面存在的字节码指令。虚拟机中执行字节码指令的部分叫做执行引擎。就像一个人,不是把饭吃下去就完事了,还需要进行消化,执行引擎就相当于人的肠胃系统。在执行过程中还会把各个class文件动态的连接起来。
Java虚拟机会进行自动内存管理。具体说来就是自动释放没有用的对象,而不需要程序员编写代码来释放分配的内存。这部分工作由垃圾收集子系统负责。
从上面的论述可知,一个Java虚拟机实例在运行过程中有三个子系统来保障它的正常运行,分别是类加载器子系统,执行引擎子系统和垃圾收集子系统。如下图所示:
虚拟机的运行,必须加载class文件,并且执行class文件中的字节码指令。它做这么多事情,必须需要自己的空间。就像人吃下去的东西首先要放在胃中。虚拟机也需要空间来存放个中数据。首先,加载的字节码,需要一个单独的内存空间来存放;一个线程的执行,也需要内存空间来维护方法的调用关系,存放方法中的数据和中间计算结果;在执行的过程中,无法避免的要创建对象,创建的对象需要一个专门的内存空间来存放。
5.总结
1)虚拟机并不神秘,在操作系统的角度来看来,它只是一个普通进程。
2)这个叫做虚拟机的进程比较特殊,它能够加载我们编写的class文件。如果把JVM比作一个人,那么class文件就是我们吃的食物。
3)加载class文件的是一个叫做类加载器的子系统。就好比我们的嘴巴,把食物吃到肚子里。
4)虚拟机的执行引擎用来执行class文件中的字节码指令。就好比我们的肠胃,对吃进去的食物进行消化。
5)虚拟机在执行过程中,要分配内存创建对象。当这些对象过时无用了,必须要自动清理这些无用的对象。清理对象回收内存的任务由垃圾收集器负责。就好比人吃进去的食物,在消化之后,必须把废物排出体外,腾出空间可以在下次の的时候吃饭并消化食物。
参考:http://blog.csdn.net/zhangjg_blog/article/details/20380971