中篇_1_字节码文件的跨平台性、前端编译器、字节码指令(代码、概念、解读)

1、字节码文件的跨平台性

  1. Java语言:跨平台的语言
    1. 当Java源代码成功编译为字节码后,如果想在不同的平台上运行,则无须再次编译
    2. 这个优势不再那么吸引人了。Python PHP perl ruby lisp等有强大的解释器
    3. 跨平台似乎已经快成为一门语言必须的特征
  2. Java虚拟机:跨语言的平台
    ( Java虚拟机不和包括java在内的任何语言绑定,只与class文件这种二进制文件格式关联。无论使用何种语言进行软件开发,只要将源文件编译为正确的Class文件,该语言就可以在Java虚拟机上执行,可以说,统一而强大的Class文件结构,就是Java虚拟机的基石、桥梁)
    在这里插入图片描述
  3. 想要让一个Java程序正确地运行在JVM中,Java源码就必须要编译为符合JVM规范的字节码
    1. 前端编译器的主要任务是负责将符合Java语言规范的Java代码转换为符合JVM规范的字节码文件
    2. javac是一种能够将Java源码编译为字节码的前端编译器
    3. javac编译器在将Java源码编译为一个有效的字节码文件过程中经历了4个步骤:分别是词法解析、语法解析、语义解析以及生成字节码

2、前端编译器 VS 后端编译器

Java源代码的编译结果是字节码。那么肯定需要有一种编译器能够将Java源码编译为字节码,承担这个重要责任的就是配置在path环境变量中的javac编译器。javac是一种能够将Java源码编译为字节码的前端编译器。

HotSpot VM并没有强制要求前端编译器只能使用javac来编译字节码,其编译结果符合JVM规范都可以被JVM所识别即可。在Java的前端编译器领域,除了javac之外,还有内置在Eclipse中的ECJ(Eclipse Compiler for java)编译器。和javac的全量式编译不同,ECJ是一种增量式编译器。

  • 在Eclipse中,当开发人员编写完代码后,使用“ctrl+s” 快捷键时,ECJ编译器所采取的编译方案是把未编译的部分源码逐行编译,而非每次都全量编译。因此ECJ的编译效率会比javac更加迅速和高效,当然编译质量与javac相比大致还是一样的。
  • ECJ不仅是Eclipse的默认内置前端编译器,在Tomcat中同样是使用ECJ编译jsp文件。由于ECJ编译器采用GPLv2的开源协议进行源代码公开,所以,可登录eclipse官网下载ECJ编译器的源码进行二次开发。
  • 默认情况下,IDEA使用 javac 编译器(也可以自己设置为 AspectJ 编译器 ajc)

前端编译器并不会直接涉及编译优化等方面的技术,具体优化细节由HotSpot的 JIT 编译器负责。
在这里插入图片描述

3、字节码指令

3.1、三个案例

①、整数范围

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
    }
}

注意第8行(红色11行)
在这里插入图片描述

②、字符串拼接创建几个变量

public class StringTest {
    public static void main(String[] args) {
        String str=new String("hello")+new String("world");
        String str1="helloworld";
        System.out.println(str==str1);
    }
}

在这里插入图片描述

③、类的继承

/*
成员变量(非静态的)的赋值过程:
 ① 默认初始化 -
 ② 显式初始化 /代码块中初始化 -
 ③ 构造器中初始化 -
 ④ 有了对象之后,可以“对象.属性”或"对象.方法"的方式对成员变量进行赋值。
 */
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             f.x是父类的,属性不存在多态值
	*/

3.2、基本概念

①、什么是字节码文件?

源代码经过编译器编译之后便会生成一个字节码文件(字节码文件数量取决于文件中有几个类)

字节码是一种二进制的类文件,它的内容是一种二进制类文件,而不像C、C++经编译器直接生成机器码。

②、什么是字节码指令(byte code)?

Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的操作码(opcode)以及跟随其后的零至多个代表此操作所需参数的操作数(operand)所构成。虚拟机中许多指令并不包含操作数,只有一个操作码
在这里插入图片描述

3.3、如何解读

  1. EditPlus 16进制查看器;Notepad++ 安装一个HEX-Editor插件,或者使用Binary Viewer
  2. 使用javap指令:jdk自带的反解析工具
  3. 使用IDEA插件:jclasslib 或 jclasslib bytecode viewer客户端工具(可视化更好)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值