当前位置: 首页 > article >正文

JVM之Synthetic

Synthetic是人造,合成的意思,在虚拟机很多地方使用ACC_SYNTHETIC表示编译器自动生成的,区别于我们自己写的程序代码。这样说可能比较模糊,我们举个例子:我们创建一个内部类,如下

public class TestInnerClass {

    public void say(String msg) {
        System.out.println(msg);
    }

    class InnerClass {
        public void sayInner() {
            say("hello");
        }
    }
}

我们用javap看一下内部类InnerClass反编译之后的情况:

完整如下:

Classfile /F:/demo/mallsystem/provider/target/classes/com/mall/test/TestInnerClass$InnerClass.class
  Last modified 2024-11-28; size 638 bytes
  MD5 checksum 9f5efd7b8d0ad50545773d2a0e198f60
  Compiled from "TestInnerClass.java"
class com.mall.test.TestInnerClass$InnerClass
  minor version: 0
  major version: 52
  flags: ACC_SUPER
Constant pool:
   #1 = Fieldref           #5.#22         // com/mall/test/TestInnerClass$InnerClass.this$0:Lcom/mall/test/TestInnerClass;
   #2 = Methodref          #6.#23         // java/lang/Object."<init>":()V
   #3 = String             #24            // hello
   #4 = Methodref          #25.#26        // com/mall/test/TestInnerClass.say:(Ljava/lang/String;)V
   #5 = Class              #27            // com/mall/test/TestInnerClass$InnerClass
   #6 = Class              #28            // java/lang/Object
   #7 = Utf8               this$0
   #8 = Utf8               Lcom/mall/test/TestInnerClass;
   #9 = Utf8               <init>
  #10 = Utf8               (Lcom/mall/test/TestInnerClass;)V
  #11 = Utf8               Code
  #12 = Utf8               LineNumberTable
  #13 = Utf8               LocalVariableTable
  #14 = Utf8               this
  #15 = Utf8               InnerClass
  #16 = Utf8               InnerClasses
  #17 = Utf8               Lcom/mall/test/TestInnerClass$InnerClass;
  #18 = Utf8               sayInner
  #19 = Utf8               ()V
  #20 = Utf8               SourceFile
  #21 = Utf8               TestInnerClass.java
  #22 = NameAndType        #7:#8          // this$0:Lcom/mall/test/TestInnerClass;
  #23 = NameAndType        #9:#19         // "<init>":()V
  #24 = Utf8               hello
  #25 = Class              #29            // com/mall/test/TestInnerClass
  #26 = NameAndType        #30:#31        // say:(Ljava/lang/String;)V
  #27 = Utf8               com/mall/test/TestInnerClass$InnerClass
  #28 = Utf8               java/lang/Object
  #29 = Utf8               com/mall/test/TestInnerClass
  #30 = Utf8               say
  #31 = Utf8               (Ljava/lang/String;)V
{
  final com.mall.test.TestInnerClass this$0;
    descriptor: Lcom/mall/test/TestInnerClass;
    flags: ACC_FINAL, ACC_SYNTHETIC

  com.mall.test.TestInnerClass$InnerClass(com.mall.test.TestInnerClass);
    descriptor: (Lcom/mall/test/TestInnerClass;)V
    flags:
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #1                  // Field this$0:Lcom/mall/test/TestInnerClass;
         5: aload_0
         6: invokespecial #2                  // Method java/lang/Object."<init>":()V
         9: return
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      10     0  this   Lcom/mall/test/TestInnerClass$InnerClass;
            0      10     1 this$0   Lcom/mall/test/TestInnerClass;

  public void sayInner();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: getfield      #1                  // Field this$0:Lcom/mall/test/TestInnerClass;
         4: ldc           #3                  // String hello
         6: invokevirtual #4                  // Method com/mall/test/TestInnerClass.say:(Ljava/lang/String;)V
         9: return
      LineNumberTable:
        line 14: 0
        line 15: 9
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      10     0  this   Lcom/mall/test/TestInnerClass$InnerClass;
}
SourceFile: "TestInnerClass.java"
InnerClasses:
     #15= #5 of #25; //InnerClass=class com/mall/test/TestInnerClass$InnerClass of class com/mall/test/TestInnerClass

重点看下面标记的,ACC_SYNTHETIC标记出现了

这里编译器在内部类生成了一个TestInnerClass的引用对象this$0,因为是编译器自动合成的,所以标记了ACC_SYNTHETIC。

而下面是内部类的构造方法,可以看到它传入了外部类的实例对象,之后把它赋值给this$0

aload_0默认是实例方法第一个参数是this,即内部类自己的引用

aload_1则是加载第一个入参也就是外部类实例对象

putfield #1就是把外部实例设置给this$0

所以这也就解释了为什么内部类创建需要外部类对象创建了,如果外部类对象还没有生成,怎么传给内部类的构造方法呢?

而我们内部类能调用外部类的方法,也正是通过外部类的实例对象调用的


http://www.kler.cn/a/417814.html

相关文章:

  • 基于单片机的微型电子琴建模
  • 架构师:Dubbo 服务请求失败处理的实践指南
  • C#面向对象之访问限制,类基础,继承
  • 1.1 数据结构的基本概念
  • 算法妙妙屋-------1.递归的深邃回响:全排列的奇妙组合
  • 什么是人工智能大模型?
  • 算法编程题-合并石头的最低成本
  • 七、传统循环神经网络(RNN)
  • PAT甲级-1143 Lowest Common Ancestor
  • 世界灌溉科技大会全球推广之旅,邀约美国、澳大利亚、土耳其等30余国采购商携千万资金到场采购
  • day21 链表
  • 免费搭建一个属于自己的个性化博客(Hexo+Fluid+Github)
  • Rk3588 onnx转rknn,出现 No module named ‘rknn‘
  • 【大数据学习 | 面经】HDFS的三副本机制和编码机制
  • Microsoft Excel如何插入多行
  • 【阿来来gis规划师工具箱说明书】h07四分标注
  • 管家婆工贸ERP BR044.当前库存余额表
  • 【kafka04】消息队列与微服务之Kafka 图形工具
  • Vue 2.0->3.0学习笔记(Vue 3 (三)- 其它 Composition API)
  • 【Pytorch】优化器(Optimizer)模块‘torch.optim’
  • QUICK 调试camera-xml解析
  • 神经网络中常见的激活函数Sigmoid、Tanh和ReLU
  • 三十一:HTTP多种重定向跳转方式的差异
  • 《FPGA开发工具》专栏目录
  • 【Rust 学习笔记】Rust 基础数据类型介绍(一)
  • idea根据实体类生成数据库表