前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >jvm类文件的入门

jvm类文件的入门

作者头像
JathonKatu
发布2021-12-31 14:56:30
2540
发布2021-12-31 14:56:30
举报
文章被收录于专栏:JathonKatu

入门代码很简单:

代码语言:javascript
复制
public class Test {
    public static void main(String[] args) {
        System.out.println("a");
    }
}
Classfile /D:/work/IDEAWorkSpace/my-study/io/target/classes/com/jathonkatu/io/bio/Test.class
  Last modified 2021-12-27; size 579 bytes
  MD5 checksum 3bae36d299be64b900ed5c05b586bf20
  Compiled from "Test.java"
public class com.jathonkatu.io.bio.Test
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#21         // java/lang/Object."<init>":()V
   #2 = Fieldref           #22.#23        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = String             #24            // a
   #4 = Methodref          #25.#26        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #5 = Class              #27            // com/jathonkatu/io/bio/Test
   #6 = Class              #28            // java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/jathonkatu/io/bio/Test;
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Utf8               args
  #17 = Utf8               [Ljava/lang/String;
  #18 = Utf8               MethodParameters
  #19 = Utf8               SourceFile
  #20 = Utf8               Test.java
  #21 = NameAndType        #7:#8          // "<init>":()V
  #22 = Class              #29            // java/lang/System
  #23 = NameAndType        #30:#31        // out:Ljava/io/PrintStream;
  #24 = Utf8               a
  #25 = Class              #32            // java/io/PrintStream
  #26 = NameAndType        #33:#34        // println:(Ljava/lang/String;)V
  #27 = Utf8               com/jathonkatu/io/bio/Test
  #28 = Utf8               java/lang/Object
  #29 = Utf8               java/lang/System
  #30 = Utf8               out
  #31 = Utf8               Ljava/io/PrintStream;
  #32 = Utf8               java/io/PrintStream
  #33 = Utf8               println
  #34 = Utf8               (Ljava/lang/String;)V
{
  public com.jathonkatu.io.bio.Test();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 8: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/jathonkatu/io/bio/Test;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String a
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 10: 0
        line 11: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  args   [Ljava/lang/String;
    MethodParameters:
      Name                           Flags
      args
}
SourceFile: "Test.java"

具体细节我们看进阶代码

进阶代码很简单:

代码语言:javascript
复制
public class Test {
    public static void main(String[] args) {
        Consumer<String> consumer = s -> System.out.println(s);
        consumer.accept("arthas");
    }
}

我们来看看javap -c -p -v Test.class之后的结果

以下所有// Jathonkatu则是我自己写的注释

javac的时候可以用-g:none或-g:vars选项来取消或要求生成LocalVariableTable的参数(也就是字段名)取消了会用var0,arg0之类的代替

可以用-g:none或-g:lines取消或者生成LineNumberTable

代码语言:javascript
复制
Classfile /D:/work/IDEAWorkSpace/my-study/io/target/classes/com/jathonkatu/io/bio/Test.class  // Jathonkatu 这里是说明class路径
  Last modified 2021-12-27; size 1429 bytes  // Jathonkatu  最后修改日期,文件大小
  MD5 checksum 954dbfeb9e7546cc4db907ed0b60a2bc  // Jathonkatu  用以校验的MD5的码
  Compiled from "Test.java"  // Jathonkatu  编译类名
public class com.jathonkatu.io.bio.Test  // Jathonkatu  类地址
  minor version: 0 // Jathonkatu  .0
  major version: 52 // Jathonkatu  52   52.0-> jdk8
  flags: ACC_PUBLIC, ACC_SUPER  // Jathonkatu  public类型,使用invokespecial字节码指令. 识别一些类或 者接口层次的访问信息,包括:这个Class是类还是接口;是否定义为public类型;是否定义为abstract 类型;如果是类的话,是否被声明为final;等等
Constant pool: // Jathonkatu  常量池
   #1 = Methodref          #8.#31         // java/lang/Object."<init>":()V  // Jathonkatu  方法符号 
   #2 = InvokeDynamic      #0:#37         // #0:accept:()Ljava/util/function/Consumer;  // Jathonkatu 动态调用点  consumer的accept方法
   #3 = String             #38            // arthas // Jathonkatu 字符串arthas 我们自己定义的
   #4 = InterfaceMethodref #39.#40        // java/util/function/Consumer.accept:(Ljava/lang/Object;)V  // Jathonkatu 接口中方法的符号引用
   #5 = Fieldref           #41.#42        // java/lang/System.out:Ljava/io/PrintStream; // Jathonkatu 字段的符号引用  System类中的字段out 是一个PrintStream的类型
   #6 = Methodref          #43.#44        // java/io/PrintStream.println:(Ljava/lang/String;)V  // Jathonkatu  方法符号引用  调用printStream的prinln方法(参数是String)
   #7 = Class              #45            // com/jathonkatu/io/bio/Test  // Jathonkatu 类或接口的符号引用  类全名
   #8 = Class              #46            // java/lang/Object  // Jathonkatu 类或接口的符号引用
   #9 = Utf8               <init>
  #10 = Utf8               ()V
  #11 = Utf8               Code
  #12 = Utf8               LineNumberTable  // Jathonkatu 行号与字节码指令的对应关系
  #13 = Utf8               LocalVariableTable  // Jathonkatu 方法的局部变量描述
  #14 = Utf8               this
  #15 = Utf8               Lcom/jathonkatu/io/bio/Test;  // Jathonkatu 类名
  #16 = Utf8               main  // Jathonkatu  方法名
  #17 = Utf8               ([Ljava/lang/String;)V // Jathonkatu String数组值
  #18 = Utf8               args  // Jathonkatu  变量名 args
  #19 = Utf8               [Ljava/lang/String;  // Jathonkatu String数组值
  #20 = Utf8               consumer  // Jathonkatu  变量名 consumer
  #21 = Utf8               Ljava/util/function/Consumer;  // 对象Consumer
  #22 = Utf8               LocalVariableTypeTable  // 方法的局部变量描述 只是一个标识符
  #23 = Utf8               Ljava/util/function/Consumer<Ljava/lang/String;>;  // 对象Consumer<String>
  #24 = Utf8               MethodParameters  // Jathonkatu  方法入参
  #25 = Utf8               lambda$main$0  // Jathonkatu  方法名
  #26 = Utf8               (Ljava/lang/String;)V  // Jathonkatu String变量值
  #27 = Utf8               s  // Jathonkatu  变量名
  #28 = Utf8               Ljava/lang/String;  // Jathonkatu String类型
  #29 = Utf8               SourceFile  // Jathonkatu  来源文件
  #30 = Utf8               Test.java  // Jathonkatu  java文件名
  #31 = NameAndType        #9:#10         // "<init>":()V  // Jathonkatu 实例构造器(无参数)部分符号引用
  #32 = Utf8               BootstrapMethods  // Jathonkatu 用于保存invokedynamic指令引用的引导方法限定符
  #33 = MethodHandle       #6:#47         // invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/
invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;  // Jathonkatu 方法句柄
  #34 = MethodType         #48            //  (Ljava/lang/Object;)V  // 方法类型
  #35 = MethodHandle       #6:#49         // invokestatic com/jathonkatu/io/bio/Test.lambda$main$0:(Ljava/lang/String;)V
  #36 = MethodType         #26            //  (Ljava/lang/String;)V  // Jathonkatu  方法类型
  #37 = NameAndType        #50:#51        // accept:()Ljava/util/function/Consumer;// Jathonkatu 方法引用 accept
  #38 = Utf8               arthas         // Jathonkatu  字符串arthas
  #39 = Class              #52            // java/util/function/Consumer  // Jathonkatu  类类型Consumer
  #40 = NameAndType        #50:#48        // accept:(Ljava/lang/Object;)V  // Jathonkatu  调用方法accept(object)
  #41 = Class              #53            // java/lang/System  // Jathonkatu System类
  #42 = NameAndType        #54:#55        // out:Ljava/io/PrintStream;  // Jathonkatu  字段类型out字段的类为PrintStream
  #43 = Class              #56            // java/io/PrintStream  // Jathonkatu  类型  
  #44 = NameAndType        #57:#26        // println:(Ljava/lang/String;)V  // Jathonkatu 引用方法println
  #45 = Utf8               com/jathonkatu/io/bio/Test  // Jathonkatu  字符串(用来表述类的包路径)
  #46 = Utf8               java/lang/Object  // Jathonkatu  父类
  #47 = Methodref          #58.#59        // java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/Method
Handle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
  #48 = Utf8               (Ljava/lang/Object;)V
  #49 = Methodref          #7.#60         // com/jathonkatu/io/bio/Test.lambda$main$0:(Ljava/lang/String;)V
  #50 = Utf8               accept
  #51 = Utf8               ()Ljava/util/function/Consumer;
  #52 = Utf8               java/util/function/Consumer
  #53 = Utf8               java/lang/System
  #54 = Utf8               out
  #55 = Utf8               Ljava/io/PrintStream;
  #56 = Utf8               java/io/PrintStream
  #57 = Utf8               println
  #58 = Class              #61            // java/lang/invoke/LambdaMetafactory
  #59 = NameAndType        #62:#66        // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType
;)Ljava/lang/invoke/CallSite;
  #60 = NameAndType        #25:#26        // lambda$main$0:(Ljava/lang/String;)V
  #61 = Utf8               java/lang/invoke/LambdaMetafactory
  #62 = Utf8               metafactory
  #63 = Class              #68            // java/lang/invoke/MethodHandles$Lookup  // Jathonkatu  类型
  #64 = Utf8               Lookup  // Jathonkatu  跳转
  #65 = Utf8               InnerClasses  // Jathonkatu  内部类文件
  #66 = Utf8               (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
  #67 = Class              #69            // java/lang/invoke/MethodHandles
  #68 = Utf8               java/lang/invoke/MethodHandles$Lookup
  #69 = Utf8               java/lang/invoke/MethodHandles
{
  public com.jathonkatu.io.bio.Test();  // Jathonkatu 类构造方法
    descriptor: ()V  // Jathonkatu  返回一个v的类型(就是占位符)
    flags: ACC_PUBLIC  // Jathonkatu public关键字
    Code:
      stack=1, locals=1, args_size=1  // Jathonkatu 栈深度,本地方法,参数个数
         0: aload_0  // Jathonkatu  应该将“this”推送到堆栈上
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V  // Jathonkatu  调用初始化方法
         4: return  // Jathonkatu  返回
      LineNumberTable:  // Jathonkatu  行号与字节码指令对应关系  前者是字节码行号,后者是源码行号
        line 9: 0 
      LocalVariableTable:  // Jathonkatu  方法的局部变量描述
        Start  Length  Slot  Name   Signature  // Jathonkatu  局部变量的生命周期的字节码偏移量开始,覆盖长度(前两个结合就是局部变量在字节码中的作用域),局部变量在栈帧局部变量表中solt的位置,如果是64位的就是solt和solt+1(double,long),局部变量的名称,局部变量的描述符(用于支持泛型)
            0       5     0  this   Lcom/jathonkatu/io/bio/Test;

  public static void main(java.lang.String[]);  //Jathonkatu    main方法
    descriptor: ([Ljava/lang/String;)V  // Jathonkatu  描述符
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: invokedynamic #2,  0              // InvokeDynamic #0:accept:()Ljava/util/function/Consumer;  // Jathonkatu 动态调用
         5: astore_1  // Jathonkatu  JVM从操作数栈顶部弹出一个引用类型或者returnAddress类型值,然后将该值存入由索引1指定的局部变量中,即将引用类型或者returnAddress类型值存入局部变量1
         6: aload_1  // Jathonkatu  获取第一个参数(args)
         7: ldc           #3                  // String arthas // Jathonkatu 该系列命令负责把数值常量或String常量值从常量池中推送至栈顶。该命令后面需要给一个表示常量在常量池中位置(编号)的参数  也就是把字节码第三行的arthas推送到栈顶
         9: invokeinterface #4,  2            // InterfaceMethod java/util/function/Consumer.accept:(Ljava/lang/Object;)V  // Jathonkatu 索引,将字节码第四行和只想第二行
        14: return  // 返回
      LineNumberTable:
        line 11: 0
        line 12: 6
        line 13: 14
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      15     0  args   [Ljava/lang/String;
            6       9     1 consumer   Ljava/util/function/Consumer;
      LocalVariableTypeTable:
        Start  Length  Slot  Name   Signature
            6       9     1 consumer   Ljava/util/function/Consumer<Ljava/lang/String;>;
    MethodParameters:  // Jathonkatu  记录形参个数,参数名
      Name                           Flags
      args

  private static void lambda$main$0(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;  // Jathonkatu  获取静态变量
         3: aload_0                           // Jathonkatu  应该将“this”推送到堆栈上
         4: invokevirtual #6                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V  // 调用虚方法,运行期动态查找的过程
         7: return
      LineNumberTable:
        line 11: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       8     0     s   Ljava/lang/String;
    MethodParameters:
      Name                           Flags
      s                              synthetic
}
SourceFile: "Test.java"  // Jathonkatu  源文件的文件名
InnerClasses: // Jathonkatu 内部类列表
     public static final #64= #63 of #67; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles  // lookup类是MethodHandles的内部类
BootstrapMethods: // Jathonkatu 用于保存invokedynamic指令引用的引导方法限定符
  0: #33 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invok
e/MethodType;)Ljava/lang/invoke/CallSite;
    Method arguments:
      #34 (Ljava/lang/Object;)V
      #35 invokestatic com/jathonkatu/io/bio/Test.lambda$main$0:(Ljava/lang/String;)V
      #36 (Ljava/lang/String;)V
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-12-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JathonKatu 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档