JVM_17_Class文件结构概述

回顾

JVM基本组成
在这里插入图片描述
在这里插入图片描述

字节码文件的跨平台性

Java语言:跨平台的语言(write once,run anywhere)

  • 当Java源代码成功编译成字节码之后,如果想在不同的平台上运行,不需要再次编译。
  • 这个优势不是很吸引人了,因为Python、PHP、Perl、Ruby、Lisp等语言都有强大的解释器
  • 跨平台已经几乎称为一门语言的必选特性

Java 虚拟机:跨语言的平台

  • Java虚拟机不和包含Java在内的任何语言进行绑定,它只和 “.class” 文件这种特定的二进制文件格式关联
  • 无论是哪一种语言,只要能够将源文件编译成正确的Class文件,那么这种语言就可以在虚拟机上运行。可以说,统一而强大的Class文件结构,就是Java虚拟机的基石和桥梁。

在这里插入图片描述

Class字节码的规范性

  • 所有的JVM都遵循Java虚拟机规范,也就是说所有的JVM环境都是一样的,这样一来字节码文件可以在各种JVM中运行
  • 想要一个Java程序正确的运行在JVM中,Java源码就必须要被编译为符合JVM规范的字节码
  • 前端编译器的主要任务就是负责将符合Java语法规范的Java代码编译成符合JVM规范的字节码
  • javac是一个能够将Java源码编译为字节码的前端编译器
  • javac编译器将Java源代码编译为一个有效的字节码文件过程中经历了4个步骤,分别是:词法解析、语法解析、语义解析以及生成字节码
    在这里插入图片描述
  • Oracle 发布的JDK软件包括2部分内容
    • 一部分是将Java源码编译成Java虚拟机的指令集的编译器
    • 一部分是用于实现Java虚拟机的运行时环境

Java的前端编译器

在这里插入图片描述
前端编译器 VS 后端编译器
在这里插入图片描述

透过字节码指令看代码执行细节

问题:

  • 类文件结构有几个部分?
  • 知道字节码吗?字节码都有哪些? Integer x = 5; int y = 5; 比较 x == y 都有哪些步骤?

代码举例一

public class IntegerTest {
    public static void main(String[] args) {

        /*
         * 透过字节码可以看出,当Integer的范围在-128 - +127 之间会在数组中直接拿取数值
         * 超过这个范围会重新new对象
         * */
        Integer x = 5;
        int y = 5;
        System.out.println(x == y); // true

        Integer i1 = 10;
        Integer i2 = 10;
        System.out.println(i1 == i2);// true

        Integer i3 = 128;
        Integer i4 = 128;
        System.out.println(i3 == i4);// false
    }
}

在这里插入图片描述
valueOf源码

public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

代码举例二

public class StringTest {
    public static void main(String[] args) {

        String str = new String("hello") +
                new String("world");
        String str2 = "helloword";
        System.out.println(str2 == str); // false

    }
}

在这里插入图片描述
代码举例三

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

Father类
在这里插入图片描述
Son类
在这里插入图片描述
Son调用构造方法之前,调用父类的构造方法 然后父类构造方法中调用 print() 方法 而子类实现了print()方法 所以此时调用子类的print()方法 打印的值为0 然后父类构造方法执行完毕 子类构造方法继续执行,此时打印30 然后子类构造方法执行完毕 然后父类对象调用属性,打印父类的x值

字节码文件里是什么?

  • 源代码经过编译器编译之后就会生成字节码文件,字节码是一种二进制的类文件。它的内容是JVM指令,而不像C、C++经由编译器直接生成机器码。

什么是字节码指令(Byte Code)

  • Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的操作码(opcode)以及跟随其后的零至多个代表此操作的所需参数的操作数(operand)所构成。虚拟机中许多指令并不包含操作数,只有一个操作码,如下:操作码 (操作数)
    在这里插入图片描述
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值