字节码与类的加载篇--1 Class文件结构 -B站尚硅谷JVM课程学习

class文件结构 类的加载 执行引擎===》
内存的结构与分配===》
垃圾回收算法与垃圾回收器===》
性能监控(命令行、可视化工具)===》
性能优化

概述

字节码文件的跨平台性:

  • java语言是跨平台的语言 write once,run anywhere
  • java 虚拟机是跨语言的平台
  • JVM 都遵循Java 虚拟机规范

java的前端编译器
在这里插入图片描述
javac编译器,前端编译器,idea默认使用javac编译器
AOT编译器:在编译之前字节码文件翻译成机器指令,适用于Linux
透过字节码指令看代码细节

		Integer x = 5;
        int y = 5;
        System.out.println(x == y);//true

在这里插入图片描述
valueOf方法源码:
low是-128,high是127

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

intValue 源码:

    public int intValue() {
        return value;
    }
package chapter201;

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);//false

        String str2 = new String("helloworld");
        System.out.println(str == str2);//false 
    }
}
package chapter201;

/**
 * 成员变量(非静态)的赋值过程:
 * 1. 默认初始化
 * 2. 显示初始化/代码中初始化
 * 3. 构造器中初始化
 * 4. 有了对象以后可以对象.属性赋值
 */
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;

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

在这里插入图片描述

虚拟机的基石:Class文件

  • 字节码文件是一个二进制的类文件,内容是JVM指令
  • 字节码指令:一个字节长度的、代表操作含义的操作码、(所需要的操作数)
    在这里插入图片描述
    在这里插入图片描述
  • 解读字节码文件:binary-view / notepad安装Hex插件,javap指令,jclasslib
    在这里插入图片描述
    在这里插入图片描述

Class文件结构

  • Class类本质:Class文件是是一组以8位字节为基础单位的二进制流
  • Class文件格式:其中数据项是严格限制的,不允许改变。无符号数和表,u1表示一个字节,u2表示两个字节;表习惯以_info结尾

Class文件结构:

  • 魔数
  • Class文件版本
  • 常量池:存放常量,内容丰富。常量池计数器,常量池表:字面量符号引用长度是计数器-1
    在这里插入图片描述
    字面量:
    String str = “xinxue”;
    final int NUM = 10;
    符号引用:
    全限定名:com/testJVM/Demo;
    描述符:用来描述字段的数据类型
    在这里插入图片描述
package chapter201;

public class ArrayTest {

    public static void main(String[] args) {
        Object[] objects = new Object[10];
        System.out.println(objects);//对象类型 一维数组 [Ljava.lang.Object;@4554617c


        String[] strings = new String[10];
        System.out.println(strings);//对象类型 一维数组 [Ljava.lang.String;@74a14482

        long[][] longs = new long[10][];
        System.out.println(longs);//long类型 二维数组 [[J@1540e19d
    }
}

补充
虚拟机运行时,需要从常量池中获得对应的符号引用,在在类加载过程中的解析阶段将其替换为直接引用,并翻译到具体的内存地址中。

  • 符号引用:以一组符号来描述引用的目标
  • 直接引用:直接执行目标的指针、相对偏移量或一个能间接定位到目标的句柄。

常量池表:
在这里插入图片描述

  • 访问标志 access_flag,
    两个字节,识别一些类和接口的访问信息
    在这里插入图片描述

  • 类索引,父类索引,接口索引集合
    在这里插入图片描述

  • 字段表集合
    字段计数器(两个字节)+字段表
    1)用于描述接口或类中声明的变量。字段包含类级变量以及实例级变量;
    2)字段叫什么名字、字段被定义为什么类型,需要引用常量池中变量来描述
    3)指向常量池索引集合,描述每个字段的完整信息。如字段标识符、访问修饰符、类变量还是实例变量、是否为常量
    4)java语言中字段是无法重载的,但是字节码如果两个字段的描述符不一致字段重名就是合法的
    5)字段表结构
    在这里插入图片描述
    字段表访问标识
    在这里插入图片描述

  • 方法表集合
    指向常量池索引集合,完整描述每个方法的签名。字节码文件中,每一个method_info项都对应着一个类或者接口中的方法信息
    在这里插入图片描述

  • 属性表集合:class文件所携带的辅助信息
    字段表、方法表都可以有自己的属性表。
    属性计数器+属性表
    属性通用格式
    在这里插入图片描述
    字节码具体解析

package chapter201;


public class Demo {
    private int num = 1;
    public int add(){
        num = num + 2;
        return num;
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

使用javap指令解析Class文件

javac (-g)A.java 编译java文件,有-g参数编译的文件有局部变量表信息

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
-v不包括私有的信息

javap -v -p A.class 打印包含私有的信息

package chapter201;

public class JavapTest {

    private int num;
    boolean flag;
    protected char gender;
    public String info;

    public static final int COUNTS = 1;

    static {
        String url = "www.baidu.com";

    }

    {
        info = "java";
    }

    public JavapTest() {

    }

    private JavapTest(boolean flag){
        this.flag = flag;
    }
    private void methodPrivate(){

    }

    int getNum(int i){
        return num + i;
    }

    protected char showGender(){
        return gender;
    }

    public void showInfo(){
        int i = 10;
        System.out.println(info + i);
    }
}

在这里插入图片描述
具体剖析:

Classfile /C:/Users/shen/Desktop/JavapTest.class  //字节码文件所属路径
  Last modified 2022-3-25; size 1342 bytes        //修改时间 字节码文件大小
  MD5 checksum 63b66c20420bb17811739794d4ab69a8   // MD5 散列值
  Compiled from "JavapTest.java"                  //源文件名称
public class chapter201.JavapTest
  minor version: 0                               //副版本
  major version: 52                              //主版本
  flags: ACC_PUBLIC, ACC_SUPER                   //访问标识
Constant pool:                                   //常量池
   #1 = Methodref          #16.#46        // java/lang/Object."<init>":()V
   #2 = String             #47            // java
   #3 = Fieldref           #15.#48        // chapter201/JavapTest.info:Ljava/lang/String;
   #4 = Fieldref           #15.#49        // chapter201/JavapTest.flag:Z
   #5 = Fieldref           #15.#50        // chapter201/JavapTest.num:I
   #6 = Fieldref           #15.#51        // chapter201/JavapTest.gender:C
   #7 = Fieldref           #52.#53        // java/lang/System.out:Ljava/io/PrintStream;
   #8 = Class              #54            // java/lang/StringBuilder
   #9 = Methodref          #8.#46         // java/lang/StringBuilder."<init>":()V
  #10 = Methodref          #8.#55         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #11 = Methodref          #8.#56         // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
  #12 = Methodref          #8.#57         // java/lang/StringBuilder.toString:()Ljava/lang/String;
  #13 = Methodref          #58.#59        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #14 = String             #60            // www.baidu.com
  #15 = Class              #61            // chapter201/JavapTest
  #16 = Class              #62            // java/lang/Object
  #17 = Utf8               num
  #18 = Utf8               I
  #19 = Utf8               flag
  #20 = Utf8               Z
  #21 = Utf8               gender
  #22 = Utf8               C
  #23 = Utf8               info
  #24 = Utf8               Ljava/lang/String;
  #25 = Utf8               COUNTS
  #26 = Utf8               ConstantValue
  #27 = Integer            1
  #28 = Utf8               <init>
  #29 = Utf8               ()V
  #30 = Utf8               Code
  #31 = Utf8               LineNumberTable
  #32 = Utf8               LocalVariableTable
  #33 = Utf8               this
  #34 = Utf8               Lchapter201/JavapTest;
  #35 = Utf8               (Z)V
  #36 = Utf8               methodPrivate
  #37 = Utf8               getNum
  #38 = Utf8               (I)I
  #39 = Utf8               i
  #40 = Utf8               showGender
  #41 = Utf8               ()C
  #42 = Utf8               showInfo
  #43 = Utf8               <clinit>
  #44 = Utf8               SourceFile
  #45 = Utf8               JavapTest.java
  #46 = NameAndType        #28:#29        // "<init>":()V
  #47 = Utf8               java
  #48 = NameAndType        #23:#24        // info:Ljava/lang/String;
  #49 = NameAndType        #19:#20        // flag:Z
  #50 = NameAndType        #17:#18        // num:I
  #51 = NameAndType        #21:#22        // gender:C
  #52 = Class              #63            // java/lang/System
  #53 = NameAndType        #64:#65        // out:Ljava/io/PrintStream;
  #54 = Utf8               java/lang/StringBuilder
  #55 = NameAndType        #66:#67        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #56 = NameAndType        #66:#68        // append:(I)Ljava/lang/StringBuilder;
  #57 = NameAndType        #69:#70        // toString:()Ljava/lang/String;
  #58 = Class              #71            // java/io/PrintStream
  #59 = NameAndType        #72:#73        // println:(Ljava/lang/String;)V
  #60 = Utf8               www.baidu.com
  #61 = Utf8               chapter201/JavapTest
  #62 = Utf8               java/lang/Object
  #63 = Utf8               java/lang/System
  #64 = Utf8               out
  #65 = Utf8               Ljava/io/PrintStream;
  #66 = Utf8               append
  #67 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #68 = Utf8               (I)Ljava/lang/StringBuilder;
  #69 = Utf8               toString
  #70 = Utf8               ()Ljava/lang/String;
  #71 = Utf8               java/io/PrintStream
  #72 = Utf8               println
  #73 = Utf8               (Ljava/lang/String;)V
############################字段表集合信息########################################
{                          
  private int num;         //字段名
    descriptor: I          //字段描述符
    flags: ACC_PRIVATE     //字段访问标识

  boolean flag;
    descriptor: Z
    flags:

  protected char gender;
    descriptor: C
    flags: ACC_PROTECTED

  public java.lang.String info;
    descriptor: Ljava/lang/String;
    flags: ACC_PUBLIC

  public static final int COUNTS;
    descriptor: I
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    ConstantValue: int 1       //常量字段属性 ConstantValue
#############################方法表集合信息#######################################
  public chapter201.JavapTest();                //构造器1的信息
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: ldc           #2                  // String java
         7: putfield      #3                  // Field info:Ljava/lang/String;
        10: return
      LineNumberTable:
        line 21: 0
        line 18: 4
        line 23: 10
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      11     0  this   Lchapter201/JavapTest;

  private chapter201.JavapTest(boolean);      //构造器2的信息
    descriptor: (Z)V
    flags: ACC_PRIVATE
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: ldc           #2                  // String java
         7: putfield      #3                  // Field info:Ljava/lang/String;
        10: aload_0
        11: iload_1
        12: putfield      #4                  // Field flag:Z
        15: return
      LineNumberTable:
        line 25: 0
        line 18: 4
        line 26: 10
        line 27: 15
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      16     0  this   Lchapter201/JavapTest;
            0      16     1  flag   Z

  private void methodPrivate();
    descriptor: ()V
    flags: ACC_PRIVATE
    Code:
      stack=0, locals=1, args_size=1
         0: return
      LineNumberTable:
        line 30: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       1     0  this   Lchapter201/JavapTest;

  int getNum(int);
    descriptor: (I)I
    flags:
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: getfield      #5                  // Field num:I
         4: iload_1
         5: iadd
         6: ireturn
      LineNumberTable:
        line 33: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       7     0  this   Lchapter201/JavapTest;
            0       7     1     i   I

  protected char showGender();
    descriptor: ()C
    flags: ACC_PROTECTED
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #6                  // Field gender:C
         4: ireturn
      LineNumberTable:
        line 37: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lchapter201/JavapTest;

  public void showInfo();
    descriptor: ()V                           //方法描述符:方法形参列表、返回值类型
    flags: ACC_PUBLIC                         //方法的访问标识
    Code:                                     //方法的Code属性
      stack=3, locals=2, args_size=1          //stack:操作数栈深度最大值;locals:局部变量表的长度;args_size:方法接收参数个数
     //偏移量:操作码     操作数  指向字符串常量池的索引
		 0: bipush        10
         2: istore_1
         3: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
         6: new           #8                  // class java/lang/StringBuilder
         9: dup
        10: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V
        13: aload_0
        14: getfield      #3                  // Field info:Ljava/lang/String;
        17: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        20: iload_1
        21: invokevirtual #11                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        24: invokevirtual #12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        27: invokevirtual #13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        30: return
		//行号表:指明当前字节码指令的便宜来那个与java源程序中代码行号的一一对应关系
      LineNumberTable:
        line 41: 0
        line 42: 3
        line 43: 30
		//局部变量表:描述内部局部变量的相关信息
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      31     0  this   Lchapter201/JavapTest;
            3      28     1     i   I

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=1, locals=1, args_size=0
         0: ldc           #14                 // String www.baidu.com
         2: astore_0
         3: return
      LineNumberTable:
        line 13: 0
        line 15: 3
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
}
SourceFile: "JavapTest.java"  //附加属性:指明当前字节码文件对应的源程序文件名
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值