①. 字节码文件的跨平台性(了解)
- ①. Java语言:跨平台的语言
- 当Java源代码成功编译为字节码后,如果想在不同的平台上运行,则无须再次编译
- 这个优势不再那么吸引人了。Python PHP perl ruby lisp等有强大的解释器
- 跨平台似乎已经快成为一门语言必须的特征
- ②. Java虚拟机:跨语言的平台:
( Java虚拟机不和包括java在内的任何语言绑定,它只与class文件这种二进制文件格式所关联。无论使用何种语言进行软件开发,只要将源文件编译为正确的Class文件,那么这种语言就可以在Java虚拟机上执行,可以说,统一而强大的Class文件结构,就是Java虚拟机的基石、桥梁)
- ③. 想要让一个Java程序正确地运行在JVM中,Java源码就必须要编译为符合JVM规范的字节码
前端编译器的主要任务
就是负责将符合Java语言规范的Java代码转换为符合JVM规范的字节码文件- javac是一种能够将Java源码编译为字节码的前端编译器
- javac编译器在将Java源码编译为一个有效的字节码文件过程中经历了4个步骤:分别是词法解析、语法解析、语义解析以及生成字节码
②. Java的前端编译器(了解)
- ①. 前端编译器 vs 后端编译器
- ②. 图解:
③. 透过字节码指令看代码细节
- ①. Integer:透过字节码可以看出,当Integer的范围在-128 - +127 之间会在数组中直接拿取数值,超过这个范围会重新new对象
public class IntegerTest {
public static void main(String[] args) {
/*
* 透过字节码可以看出,当Integer的范围在-128 - +127 之间会在数组中直接拿取数值
* 超过这个范围会重新new对象
* */
Integer x = 5;
int y = 5;
System.out.println(x == y);
Integer i1 = 10;
Integer i2 = 10;
System.out.println(i1 == i2);//true
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3 == i4);//false
}
- ②. 在父类中调用方法,如果子类有重写,那么调用的是子类的方法,如代码中的this.print( )
注意:这里的this是指的 new son( )
/*
成员变量(非静态的)的赋值过程:
① 默认初始化 -
② 显式初始化 /代码块中初始化 -
③ 构造器中初始化 -
④ 有了对象之后,可以“对象.属性”或"对象.方法"
的方式对成员变量进行赋值。
*/
class Father {
int x = 10;
public Father() {
this.print();
x = 20;
}
public void print() {
System.out.println("Father.x = " + x);
}
}
class Son extends Father {
int x = 30;
// float x = 30.1F;
public Son() {
this.print();
x = 40;
}
public void print() {
System.out.println("Son.x = " + x);
}
}
public class SonTest {
public static void main(String[] args) {
Father f = new Son();
System.out.println(f.x);//编译看左边,执行也看左边
}
}
/*
son.x=0
son.x=30
20
*/
④. 如何解读供虚拟机解释执行的二进制字节码?
-
①. 一个一个二进制的看。这里用到的是Notepad++,需要安装一个HEX-Editor插件,或者使用Binary Viewer
-
②. 使用javap指令:jdk自带的反解析工具
-
③. 使用IDEA插件:jclasslib 或jclasslib bytecode viewer客户端工具(可视化更好)
⑤. 什么是字节码指令
- Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的操作码(opcode)以及跟随其后的零至多个代表此操作所需参数的操作数(operand)所构成。虚拟机中许多指令并不包含操作数,只有一个操作码
比如:操作码(操作数)