本篇主要讲解java的跨平台特性—“一次编译,处处运行”,正是这个核心优势使得java语言在互联网大爆发的时候能快速占领编程领域的头把交椅。

一、Java简介

Java是由Sun Microsystems公司于1995年推出的高级编程语言,几乎可以应用到所有型号和规模的设备上。

Java领域的技术有Java SE、Java EE以及Java ME。其中Java SE是基础。学习其他技术必须要有Java SE的基础。

  • Java SE:主要用于桌面程序、控制台开发
  • Java ME:嵌入式开发、手机、小家电
  • Java EE:企业级开发,网络开发和基于B/S模式的编程

在当今的软件开发行业中,Java已经成为了绝对的主流,其中最重要的原因就是Java的跨平台性。使用Java语言编写出来的程序几乎不需要任何修改就能够同时在Windows、MacOS、UNIX等平台运行。

二、Java的跨平台原理

Java程序一共要经历三个步骤:编码、编译、运行

1、第一步是编码,这步是基础,没什么好说的。java源程序的后缀名为.java

2、第一次编译,源程序编写完成后,需要一个“翻译官”来将java源程序“翻译”成与平台无关的字节码文件(bytecode)。而这个翻译官就是Java编译器(java compiler),简称javac。正是这一特性使一次编译处处运行成为可能。

获取class字节码文件常用的三种方法

Class clazz = Class.forName("包.类名称")  //在源文件阶段获取class字节码文件
Class clazz = 类名.Class  //在编译阶段获取class字节码文件
Class clazz = 类对象.getClass() //在运行阶段通过生成的对象的来获取class字节码文件 
    //这三种方法获取的类对象是同一个。

第二次"编译"(运行),将字节码文件解释成二进制的机器语言,这一步是由Java虚拟机—JVM(Java Virtual Machine)来完成的。JVM虚拟机是平台相关的。

JVM是如何完成这一步骤的呢?(以下来源于网络

1、运行时,ByteCode由JVM逐条送给解释器,解释器将翻译成机器码运行。

2、运行时,部分ByteCode可能由实时编译器(Just In Time Compiler,JIT)编译为目标机器码再执行(以method为翻译单位,还会保存起来,第二次执行就不用再翻译为机器码了),因为考虑到有些JVM是采用纯JIT编译方式实现的,其内部没有解释器,例如:JRockit、Maxine VM。

3、RTSJ,继javac之后执行AOT二次编译,生成静态的目标平台码。

有的时候,可能是以上三种方式同时在使用,至少,1和2是同时使用的,3则需要程序员手工指定。

三、这里提出一个问题,Java语言时编译型还是解释型的呢?

大家都知道,计算机不能直接理解高级语言,只能理解和运行机器语言。必须要把高级语言翻译成机器语言,计算机才能运行高级语言所编写的程序。
翻译的方式有两种,一个是编译,一个是解释

用编译型语言写的程序执行之前,需要一个专门的编译过程,通过编译系统把高级语言翻译成机器语言,把源高级程序编译成为机器语言文件,以后直接运行而不需要再编译了,所以一般编译型语言的程序执行效率高。

解释型语言在运行的时候才解释成机器语言,每个语句都是执行时才翻译。每执行一次就要翻译一次,效率较低。

二者之间最大的区别就在于是否存下目标机器码:编译会把输入的源程序以某种单位(例如基本块/函数/方法/trace等)翻译生成目标机器码,并存下来(无论是在磁盘上或是内存中)后续执行可以复用;解释则是把源程序中的指令逐条解释执行,边解释边执行,不存下目标代码,后续执行没有可以复用的信息。

Java 是一种兼具编译和解释特性的语言,.java 文件会被编译成与平台无关的 .class 文件,但是 .class 字节码文件无法被计算机直接使用,仍然需要 JVM 将其翻译成机器语言。
所以严格意义上来说,Java 是一种解释型语言(但其具有编译特性)。

下面引用一段见解

很多资料说,C/C++等是编译型语言,而Java、C#、Python、JavaScript都是解释型语言,是通过解释器来实现的,其实这么说很容易引起误解:语言一般只会定义其抽象语义,而不会强制性要求采用某种实现方式,例如说C一般被认为是编译型语言,但C的解释器也是存在的,例如Ch……所以一般被称为“解释型语言”的是主流实现方式为解释器的语言,但并不是说它就无法编译。

这里我按自己的理解解读以下,JVM在将字节码转换成机器码的过程中可能出现编译,也可能出现解释模式。但主流或者大多数情况下是解释型,所以严格意义来说Java是一门解释型的语言。