第一章 对Java平台的认知(2)——跨平台特性

第一章 对Java平台的认知(2)——跨平台特性
一、什么是JVM?为什么JAVA可以一次编译到处执行
        对于计算机而言,它只能识别0、1序列的机器指令,因此编程语言最终都要转化为这种机器指令,才能被计算机执行。而最后这种01机器指令,对应硬件则是与或非门。
        知道了计算机是如何运行程序的,那么接下来就来首先分析一下,为什么C/C++不能跨平台运行?
        首先需要分析C/C++的编译执行过程,如下图 1:

    图 1

        假设我们的C语言程序是Hello.c,在点击编译运行后,首先会通过预处理器(cpp)进行预处理,生成Hello.i,之后通过编译器(ccl)将其编译为汇编语言文件Hello.s,之后再由汇编器as编译为机器语言指令。也就是二进制文件了。最后则是一个链接阶段,也就是调用printf()函数。最后输出可执行的目标二进制文件。
        总结:就是对于计算机而言,它识别的是0、1的指令,但是直接输入指令太繁琐,所以最后发明了汇编语言,来简化程序。但是随着程序的越来越复杂,为了提高效率,人们又发明了高级语言,比如c,在编写程序的时候,c语言会被编译器便以为汇编程序,然后汇编程序再通过汇编器编译为可执行的二进制文件,也就是0、1序列。这样计算机就可以执行了。
          不论是何种高机器语言,最后都是转化为二进制机器码来执行。

          但是问题来了,不同公司生产的芯片,他们的指令集不同,比如说intel的复杂指令集和arm的精简指令集。那么一段二进制 0101010101,在不同的芯片中,可能对应不同的指令,也可能一个是加,一个是减,也可能没有这个指令集。
          那么此时回到问题:为什么c语言不能跨平台运行?
          跨平台运行,不是指这个Hello.c放在windows和linux下去运行,因为这个Hello.c说白了只是一个文本文件,运行,指的是编译后的结果去运行,比如说我在windows编译一个Hello.c,得到了一个二进制机器码,在windows的对应芯片下执行相应的指令集,但是这个编译结果如果直接拿到linux下去执行,由于指令集不同,因此对应的输入结果不同。此外同一个程序,在不同的平台,不同的cpu,可能编译出的二进制机器码的文件的格式不同(比如在windows编译出exe格式,在mac下为out格式),也可能文件格式相同,但是对应同一二进制序列的指令不同。因此无法做到跨平台。
         现在让我们来回答,为什么C语言不能跨平台运行?因为不同平台的cpu可能不同,那么对应的指令集也可能不同,编译后的文件格式也可能不同。
          也会有人说,既然编译结果不同,那个源程序一样啊,只要把源程序在对应平台上再执行一下就好了。错,因为在不同平台中,c语言的标准也有差异,比如下图 2:

图 2
        可以看到,对于long型,在linux 32位下是4字节,但是在64位则是8字节。因此即使是同样的源程序,long值较大,超过4字节但是小于8字节,在linux64上编译没问题,但是在windows64上则会越界。

        那么思考一个问题,无法跨平台的原因是,编译后的编译结果不一定相同,而不同cpu对应的指令集不同。那么如果可以解决这两个问题,就可以实现跨平台。如何解决?
        (1)保持编译结果相同。即源程序编译后的问题格式和内容相同。
        (2)设定一个适配机制,可以把同样的编译结果根据平台的不同转化为对应的指令集。即同样的编译结果,在不同平台不同指令集对应的结果相同。
          这样的话,不管是在什么平台得到的编译结果,拿到不同的平台下,只要有这个适配机制,转化为该平台对应的指令集。这样就可以实现一次编译,到处运行。
         JAVA就是基于这个思路来实现跨平台,只是这里的编译结果为class字节码文件,是一种由java虚拟机定义的二进制格式,并不是可以直接被cpu执行的二进制机器码。而适配机制则是通过安装JAVA虚拟机实现将class文件转化为机器码。为了达到这种适配效果,因此为不同平台上安装的java虚拟机不同,通过各个平台的虚拟机运行字节码文件后,运行的结果自然是一致的。  

二、JAVA虚拟机特性
             前面已经讲了java为什么可以跨平台,现在我们来讲一下java虚拟机的特性。
     (1)平台无关性
             和C/C++相比,之所以可以实现跨平台,核心在与虚拟机。正是虚拟机去做各个平台和cpu的差异化适配。
     (2)语言无关性
             java虚拟机不关心class文件是来自于哪里,只要符合规范的class文件,就可以执行。

 三、JAVA常见的编译器
        (1)前端编译器:把java文件转化为class文件
        (2)JIT编译器:将字节码转化为机器码
        (3)AOT编译器:直接把java文件编译为机器码
四、JDK与JRE
         1、JRE
              JRE,全称Java RunTime EnvironMent,也就是Java 运行环境,主要由Java SE API和JVM组成,其中Java SE API涵盖了各式常用的链接库,比如说集合(collection)、输入输出、JDBC、以及窗口程序AWT/SWING等。 这里需要明白一点,JRE运行的是class文件,而不是.java文件。而.class文件编译为可执行的二进制机器码则是通过JVM来完成的。
        2、JDK
              JDK,全称Java Development kit,也就是java开发工具包。主要是由java程序语言、Java工具程序、和JRE组成。

五、关于安装JDK后,JDK中的JRE和外面的JRE有什么区别?
         关于这个,说实话,我看的一头雾水,很多人说,JDK中的jre比外部的jre多了一个server文件夹,但是事实是,我的两个jre都有server文件夹,而且文件都相同。
         那么接下来就来对这两个jre做一个简单的对比,首先为什么会有两个jre,因为jdk中本身就有jre,而在安装选项中,会有四个选项供你选择:开发工具、源码、演示程序、public jre,对了,最后的这个就是你目录中与jdk同级的那个jre。那么这个public jre和jdk里的jre有什么区别?
        从内容上来说,两个jre大体相同。
       从职能上来说,有细微差距,因为他们针对的用户不同。如果用户需要执行java程序,那么使用public jre就可以,而无需装jdk。
        如果用户是开发人员,那么就需要安装jdk,在编译程序时,系统会优先选择开发工具所在目录或者父目录,也就是jdk下的jre。

六、class文件是不是二进制文件?
         之前在网上看到有人对于class文件的定义有疑惑,这里着重说明一下,class文件是二进制文件,但它是java虚拟机特定的二进制文件,不同于计算机直接执行的二进制机器码,这里的class文件是字节码文件,需要由java虚拟机进一步转化为二进制机器码。(具体可以看一下《 深入理解Java虚拟机》




猜你喜欢

转载自blog.csdn.net/ckq5254/article/details/79487189
今日推荐