今天看书的时候突然想到了一个关于虚拟机的问题,jvm到底是如何屏蔽掉底层的操作系统而到达跨平台的。我们知道java的虚拟机一般都是这么解释的“Java虚拟机(JVM)是Java Virtual Machine的缩写,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能模拟来实现的。Java虚拟机有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统”。
当我们编译java源文件的时候,编译器对源码进行编译,将他们编译成只有jvm“认识”的字节码文件(只有0101组成的代码),对于这些2进制代码,只要是计算机都能进行执行,当让,包含了对应的上下文的情况下。其实对于虚拟机这个东西我不太懂,毕竟都是在一个cpu和寄存器中执行指令,何来虚拟一说?,如何虚拟?还有,对于不同的平台,为什么会要有平台差异,差异在哪里,执行相同逻辑甚至相同代码为在不同平台上进行执行的时候到底有和差异?
让我们看一个简单的java代码清单:public class Jvm{
static{
System.out.println("this is a test");
}
}
下面是其字节码信息:
public class Jvm extends java.lang.Object{
public Jvm();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
static {};
Code:
0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3; //String this is a test
5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
其实这些反汇编的字节码其实真正代码的还是2进制代码,这些代码+上下文信息只有jvm知道,每一条指令对应的2进制代码比如aload_0,将位置为0的对象引用局部变量压入栈中(这是逻辑上的,真是情况还是将内存中的某一个地址传递给内存的另外一个变量,然后进行方法的执行,最后返回这个地址并且给这个地址和后N个地址中存储相应的值,这就是类的初始化),可以在cpu中可以是10011.....可以是00111....这取决于不同操作平台对于地址转移指令的具体实现,就像是不同的文件格式linux可以打开,windows都不能识别,因为操作系统对于文件的解析和执行是需要特定的标识或者格式,这些表示和格式内嵌于操作系统中。
关于如何实现虚拟机,我看了深入理解java虚拟机,具体讲的是很好,可是我没学过C(仅仅懂一点),所以那些jvm规范很难实现,反正最后说简单点,java的跨平台是通过相同2进制代码在不同平台上不同的执行机制,达到的功能还是一样的。。