Java跨平台性是通过JVM(Java虚拟机)来实现的。
JVM是不具有跨平台性的,针对不同的平台分别设计了对应的JVM。通过不同平台的JVM来实现了Java程序的跨平台性。也就是通过JVM的不跨平台性来支持Java程序的跨平台性。
Java代码的执行:
编译:Java源码通过javac命令编译成class字节码文件。
解释执行:class字节码文件通过java命令解释执行。
Java源码->编译->class字节码文件->解释器解释执行
注意,class字节码文件是与特定硬件平台无关的中间代码,从而实现了在不同平台上的JVM上的解释执行,实现跨平台性。
Java字节码的两种执行方式:
即时编译:解释器(JVM)将字节码编译成对应硬件平台的机器码(二进制指令),然后再在该平台上直接执行该机器码,速度快,效率高。
解释执行:解释器每次解释并执行字节码中的一小段代码,从而实现字节码的执行。
Java程序执行与C/C++程序执行对比:
JVM相当于80x86计算机。
JVM中的Java解释器相当于80x86 CPU。
在80x86 CPU上运行的是C/C++源码编译之后的机器码,在JVM解释器上运行的是Java源码编译之后的字节码。
当前不是所有平台都提供了JVM的,因此,Java代码只能在已经实现了JVM软件的并且安装了JVM软件的平台上运行。
javac命令就是java编译器。
java命令就是java解释器。利用解释器去装载字节码的时候,会自动的启动jvm虚拟机。使字节码在jvm内部运行。
Java源文件编译过程:
Java应用程序的开发周期包括编译、下载、解释和执行几个部分。Java编译程序将Java源程序翻译为JVM可执行代码—字节码。这一编译过程同C/C++的编译有些不同。当C编译器编译生成一个对象的代码时,该代码是为在某一特定硬件平台运行而产生的。因此,在编译过程中,编译程序通过查表将所有对符号的引用转换为特定的内存偏移量,以保证程序运行。Java编译器却不将对变量和方法的引用编译为数值引用,也不确定程序执行过程中的内存布局,而是将这些符号引用信息保留在字节码中,由解释器在运行过程中创建内存布局,然后再通过查表来确定一个方法所在的地址。这样就有效的保证了Java的可移植性和安全性。
解释器解释执行分为3步:
代码的装入、代码的校验、代码的执行。
运行JVM字节码的工作是由解释器来完成的。解释执行过程分三步进行:代码的装入、代码的校验和代码的执行。装入代码的工作由“类装载器”(class loader)完成。类装载器负责装入运行一个程序需要的所有代码,这也包括程序代码中的类所继承的类和被其调用的类。当类装载器装入一个类时,该类被放在自己的名字空间中。除了通过符号引用自己名字空间以外的类,类之间没有其他办法可以影响其它类。在本台计算机上的所有类都在同一地址空间内,而所有从外部引进的类,都有一个自己独立的名字空间。这使得本地类通过共享相同的名字空间获得较高的运行效率,同时又保证它们与从外部引进的类不会相互影响。当装入了运行程序需要的所有类后,解释器便可确定整个可执行程序的内存布局。解释器为符号引用同特定的地址空间建立对应关系及查询表。通过在这一阶段确定代码的内存布局,Java很好地解决了由超类改变而使子类崩溃的问题,同时也防止了代码对地址的非法访问。
随后,被装入的代码由字节码校验器进行检查。校验器可发现操作数栈溢出,非法数据类型转换等多种错误。通过校验后,代码便开始执行了。
Java基础类库,都内置在jdk中。
demo目录是提供的一些例子程序。
lib目录就是提供的一些基础类库。
jre目录就是运行时环境。
linux/unix下,换行是一个字符来表示的,ascII表示就是10。
windows下,换行是两个字符来表示,实际是回车+换行,ascII表示就是13和10。来表示一个回车+换行。
Java中所有功能都需要通过类来完成,也就是说Java中最小组织单位就是类。
JDK、JRE、JVM关系示意图
JRE (Java Runtime Environment) :是Java程序的运行时环境,包含 JVM 和运行时所需要的 核心类库 。
JDK (Java Development Kit):是Java程序开发工具包,包含 JRE 和开发人员使用的工具。
我们想要运行一个已有的Java程序,那么只需安装 JRE 即可。
我们想要开发一个全新的Java程序,那么必须安装 JDK 。
三者关系: JDK > JRE > JVM