class类文件以及类加载机制(一)

时间:2021-01-08 19:54:44

class类文件结构

定义:任何一个class文件都对应着惟一一个类或接口的定义信息,反过来说,类和接口并不一定都定义在文件里。class文件是一组以8位字节为基础单位的二进制流,各项数据项目严格按照顺序紧凑排列在class文件中。中间没有任何分隔符,这使得整个class文件中存储的内容几乎是程序运行的必要数据,没有间隙。当遇到需要占用8位字节以上空间的数据项时,则会按照高位在前的方式分割成若干个8位字节进行存储。
class类文件以及类加载机制(一)

class文件格式采用伪结构,该种结构中只有两种数据类型:无符号数和表。

无符号数:u1,u2,u4,u8分别代表1个字节,2个字节,4个字节,8个字节的无符号数。无符号数用来描述数字、索引引用、数量值或者按照UTF-8编码构成字符串值。
:由多个无符号数或者其他表作为数据项构成的复合数据类型,所有表都习惯性以”_info”结尾,整个class文件本质上就是一张表。

接下来,我们会直接从一个class字节码文件分析,这个事例代码是最近写的一个利用redis抢占资源结合发布订阅防并发的案例。我在讲述每个点的时候,大家可以从下面这个字节码中找到对应的位置,对比起来学习。
1、每个class文件的头四个字节称为魔数,它的唯一作用是确定这个文件是否为一个被虚拟机接受的class文件。
class类文件以及类加载机制(一)

2、紧接着魔数的4个字节存储的是class文件的版本号,第5、6是次版本号,第7、8是主版本号。笔者这里是50。版本号向下兼容,低版本的jdk是不接受高版本的class文件的。
class类文件以及类加载机制(一)
class类文件以及类加载机制(一)

3、紧接着主次版本号之后的是常量池入口,常量池可以理解为class文件之中的资源仓库,它是class文件结构中与其他项目关联最多的数据类型,也是占用Class文件空间最大的数据项目之一,同时还是Class文件中第一个出现的表类型数据项目。由于常量的数量是不固定的,所以常量池入口需要防止一个u2类型的数据,代表常量池容量的计数值。注意这个容量的技术是从1开始的。事例中0x00D3=211,210个常量,索引值范围是1~210,设计者把索引为0空出来原因考虑到,满足后面某些指向常量池的索引值的数据在特定情况下需要表达”不引用任何一个常量池项目”的含义,这种情况就可以把索引值置为0来表示。
常量池主要存放了两大类常量:字面量和符号引用。
字面量:比较接近于java语言层面的常量概念,比如文本字符串、final的常量值。
符号引用:类和接口的全限定名、字段的名称和描述符、方法的名称和描述符
由于虚拟机加载Class文件的时候进行动态链接,也就是说,在Class文件中不会保存各个方法、字段的最终内存布局信息,因为这些字段、方法的符号引用不经过运行期转换的话无法得到真正的内存入口地址,也就无法直接被虚拟机使用。JVM运行时,从常量池中获取对应的符号引用,再在类加载中翻译到具体的内存地址之中。(类加载机制我们回头再说,目的是搞清楚我们的文件如何运行起来的。)
常量池中每一项都是一个表,1.7时,14种表,每一个表开始的第一位是一个u1类型的标志位,代表着这个常量属于哪种常量类型。
class类文件以及类加载机制(一)

我们看一下事例中,常量池中的第一个常量:
0x0A=10表示类中方法的符号引用。请看截图
class类文件以及类加载机制(一)
class类文件以及类加载机制(一)

既然到了这里,我们先看CONSTANT_Fieldref_info这个表:
结构是:
class类文件以及类加载机制(一)
我们可以看到方法索引index=0x002F(47),同理第二个索引是0x006C(108)
class类文件以及类加载机制(一)
我们直接从class文件中定位,常量池中的这2个索引的位置:
第一个索引:#47 = Class #160 // java/lang/Object
第二个索引:#108 = NameAndType #64:#65 // “”:()V
对比之前我们确认的第一项常量是:
#1 = Methodref #47.#108 // java/lang/Object.””:()V
注意:字节码文件其实是把索引值都表示出来了,这样我们阅读起来很方便。看下面截图
class类文件以及类加载机制(一)
class类文件以及类加载机制(一)
class类文件以及类加载机制(一)

我们接着往下看: 这表示一个CONSTANT_Class_info
class类文件以及类加载机制(一)
我们再看一下CONSTANT_Class_info的结构:
class类文件以及类加载机制(一)
我们找一下它的类索引–0x006D(109)–找到常量池中的第109个:
class类文件以及类加载机制(一)
上图中展示的就是CONTANT_Utf8_info,我们再来看一下CONTANT_Utf8_info结构:
class类文件以及类加载机制(一)

4、在常量池结束后,紧接着的两个字节代表访问标志,这个标志用于识别一些类或者接口层次的访问信息,包括:还这个Class是类还是接口;是被定义为public类型;是否定义为abstract;如果是类的话,是否被声明为final等。具体标志位见下图:
class类文件以及类加载机制(一)

5、类索引、父类索引、接口索引集合:
类索引和父类索引都是一个u2类型的数据,而接口索引集合是一组u2类型的数据的集合。
类索引用于确定这个类的全限定名。
父类索引用于确定这个父类的全限定名。
接口索引则用来描述这个类实现了哪些接口。
这三个索引都按顺序排列在访问标志之后。这里的索引指向常量池里的常量类,然后再去定位到常量类里的index对应的CONSTANT_Utf8_info

6、字段表集合
7、方法表集合
8、属性表集合
9、字节码指令
10、类加载机制

本次先分享到这里,参考《深入jvm虚拟机》,同时拿了几个其他博友的图片,感谢~

D:\jdk8_64\bin\javap.exe -verbose PublishAndSubscribe.class
Classfile /F:/ormosia/sfeicuss_V20180205/sfeicuss-common/target/classes/com/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe.class
  Last modified 2018-2-9; size 4220 bytes
  MD5 checksum 15a03f715334231b3b1b664172c81cdc
  Compiled from "PublishAndSubscribe.java"
public class com.suning.epps.sfeicuss.common.anticoncurrency.PublishAndSubscribe
  minor version: 0
  major version: 50
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
    #1 = Methodref          #47.#108      // java/lang/Object."<init>":()V
    #2 = Class              #109          // com/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe$1
    #3 = Methodref          #2.#110       // com/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe$1."<init>":(Lcom/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe;)V
    #4 = Fieldref           #7.#111       // com/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe.threadLocal:Ljava/lang/ThreadLocal;
    #5 = Class              #112          // java/lang/StringBuilder
    #6 = Methodref          #5.#108       // java/lang/StringBuilder."<init>":()V
    #7 = Class              #113          // com/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe
    #8 = String             #114          // PUBANDSUB_KEY_
    #9 = Methodref          #5.#115       // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #10 = Methodref          #5.#116       // java/lang/StringBuilder.toString:()Ljava/lang/String;
   #11 = String             #54           // PUB_KEY
   #12 = Methodref          #117.#118     // com/suning/epps/sfeicuss/common/util/RedisClientUtils.incr:(Ljava/lang/String;)Ljava/lang/Long;
   #13 = Methodref          #119.#120     // java/lang/Long.longValue:()J
   #14 = Fieldref           #7.#121       // com/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe.LOGGER:Lorg/slf4j/Logger;
   #15 = String             #122          // 抢占到资源
   #16 = InterfaceMethodref #123.#124     // org/slf4j/Logger.debug:(Ljava/lang/String;)V
   #17 = String             #125          // false
   #18 = InterfaceMethodref #126.#127     // com/suning/epps/sfeicuss/common/anticoncurrency/CallBack.process:()Ljava/lang/Object;
   #19 = InterfaceMethodref #126.#128     // com/suning/epps/sfeicuss/common/anticoncurrency/CallBack.handlerIsSuccessOrNot:(Ljava/lang/Object;)Z
   #20 = String             #129          // 业务结果:{}
   #21 = Methodref          #130.#131     // java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
   #22 = InterfaceMethodref #123.#132     // org/slf4j/Logger.debug:(Ljava/lang/String;Ljava/lang/Object;)V
   #23 = Class              #133          // java/lang/Exception
   #24 = String             #134          // 回调业务处理异常
   #25 = InterfaceMethodref #123.#135     // org/slf4j/Logger.error:(Ljava/lang/String;Ljava/lang/Throwable;)V
   #26 = Class              #136          // com/suning/epps/sfeicuss/common/exception/AppException
   #27 = Fieldref           #137.#138     // com/suning/epps/sfeicuss/common/enums/ResponseCode.ERROR:Lcom/suning/epps/sfeicuss/common/enums/ResponseCode;
   #28 = Methodref          #137.#139     // com/suning/epps/sfeicuss/common/enums/ResponseCode.getCode:()Ljava/lang/String;
   #29 = Methodref          #26.#140      // com/suning/epps/sfeicuss/common/exception/AppException."<init>":(Ljava/lang/String;Ljava/lang/String;)V
   #30 = Methodref          #117.#141     // com/suning/epps/sfeicuss/common/util/RedisClientUtils.putBeanObj:(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;
   #31 = String             #142          // true
   #32 = Methodref          #117.#143     // com/suning/epps/sfeicuss/common/util/RedisClientUtils.del:(Ljava/lang/String;)Ljava/lang/Long;
   #33 = Methodref          #117.#144     // com/suning/epps/sfeicuss/common/util/RedisClientUtils.publish:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Long;
   #34 = Methodref          #117.#145     // com/suning/epps/sfeicuss/common/util/RedisClientUtils.subscribe:(Ljava/lang/String;)Ljava/lang/String;
   #35 = String             #77           // subMsg
   #36 = Methodref          #146.#147     // java/lang/String.equals:(Ljava/lang/Object;)Z
   #37 = Methodref          #117.#148     // com/suning/epps/sfeicuss/common/util/RedisClientUtils.getBeanObj:(Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;
   #38 = String             #149          // 收到订阅消息:{}
   #39 = InterfaceMethodref #126.#150     // com/suning/epps/sfeicuss/common/anticoncurrency/CallBack.handlerResult:(Ljava/lang/Object;)Ljava/lang/Object;
   #40 = Methodref          #151.#152     // java/lang/ThreadLocal.get:()Ljava/lang/Object;
   #41 = Class              #153          // java/lang/Integer
   #42 = Methodref          #41.#154      // java/lang/Integer.intValue:()I
   #43 = Methodref          #7.#155       // com/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe.execute:(Ljava/lang/String;Ljava/lang/Class;ILcom/suning/epps/sfeicuss/common/anticoncurrency/CallBack;)Ljava/lang/Object;
   #44 = String             #156          // 超过重试次数
   #45 = Methodref          #26.#157      // com/suning/epps/sfeicuss/common/exception/AppException."<init>":(Ljava/lang/String;)V
   #46 = Methodref          #158.#159     // org/slf4j/LoggerFactory.getLogger:(Ljava/lang/Class;)Lorg/slf4j/Logger;
   #47 = Class              #160          // java/lang/Object
   #48 = Utf8               InnerClasses
   #49 = Utf8               LOGGER
   #50 = Utf8               Lorg/slf4j/Logger;
   #51 = Utf8               PUBANDSUB_KEY
   #52 = Utf8               Ljava/lang/String;
   #53 = Utf8               ConstantValue
   #54 = Utf8               PUB_KEY
   #55 = Utf8               MSG_TRUE
   #56 = Utf8               MSG_FALSE
   #57 = Utf8               RETRY_TIME
   #58 = Utf8               I
   #59 = Integer            3
   #60 = Utf8               threadLocal
   #61 = Utf8               Ljava/lang/ThreadLocal;
   #62 = Utf8               Signature
   #63 = Utf8               Ljava/lang/ThreadLocal<Ljava/lang/Integer;>;
   #64 = Utf8               <init>
   #65 = Utf8               ()V
   #66 = Utf8               Code
   #67 = Utf8               LineNumberTable
   #68 = Utf8               LocalVariableTable
   #69 = Utf8               this
   #70 = Utf8               Lcom/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe;
   #71 = Utf8               execute
   #72 = Utf8               (Ljava/lang/String;Ljava/lang/Class;ILcom/suning/epps/sfeicuss/common/anticoncurrency/CallBack;)Ljava/lang/Object;
   #73 = Utf8               e
   #74 = Utf8               Ljava/lang/Exception;
   #75 = Utf8               msg
   #76 = Utf8               time
   #77 = Utf8               subMsg
   #78 = Utf8               key
   #79 = Utf8               clazz
   #80 = Utf8               Ljava/lang/Class;
   #81 = Utf8               retryTime
   #82 = Utf8               callBack
   #83 = Utf8               Lcom/suning/epps/sfeicuss/common/anticoncurrency/CallBack;
   #84 = Utf8               result
   #85 = Utf8               Ljava/lang/Object;
   #86 = Utf8               pasKey
   #87 = Utf8               pubKey
   #88 = Utf8               incr
   #89 = Utf8               J
   #90 = Utf8               flag
   #91 = Utf8               Z
   #92 = Utf8               LocalVariableTypeTable
   #93 = Utf8               Ljava/lang/Class<TT;>;
   #94 = Utf8               TT;
   #95 = Utf8               StackMapTable
   #96 = Class              #160          // java/lang/Object
   #97 = Class              #161          // java/lang/String
   #98 = Class              #113          // com/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe
   #99 = Class              #162          // java/lang/Class
  #100 = Class              #163          // com/suning/epps/sfeicuss/common/anticoncurrency/CallBack
  #101 = Class              #133          // java/lang/Exception
  #102 = Utf8               <T:Ljava/lang/Object;>(Ljava/lang/String;Ljava/lang/Class<TT;>;ILcom/suning/epps/sfeicuss/common/anticoncurrency/CallBack;)TT;
  #103 = Utf8               <clinit>
  #104 = Utf8               SourceFile
  #105 = Utf8               PublishAndSubscribe.java
  #106 = Utf8               RuntimeVisibleAnnotations
  #107 = Utf8               Lorg/springframework/stereotype/Service;
  #108 = NameAndType        #64:#65       // "<init>":()V
  #109 = Utf8               com/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe$1
  #110 = NameAndType        #64:#164      // "<init>":(Lcom/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe;)V
  #111 = NameAndType        #60:#61       // threadLocal:Ljava/lang/ThreadLocal;
  #112 = Utf8               java/lang/StringBuilder
  #113 = Utf8               com/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe
  #114 = Utf8               PUBANDSUB_KEY_
  #115 = NameAndType        #165:#166     // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #116 = NameAndType        #167:#168     // toString:()Ljava/lang/String;
  #117 = Class              #169          // com/suning/epps/sfeicuss/common/util/RedisClientUtils
  #118 = NameAndType        #88:#170      // incr:(Ljava/lang/String;)Ljava/lang/Long;
  #119 = Class              #171          // java/lang/Long
  #120 = NameAndType        #172:#173     // longValue:()J
  #121 = NameAndType        #49:#50       // LOGGER:Lorg/slf4j/Logger;
  #122 = Utf8               抢占到资源
  #123 = Class              #174          // org/slf4j/Logger
  #124 = NameAndType        #175:#176     // debug:(Ljava/lang/String;)V
  #125 = Utf8               false
  #126 = Class              #163          // com/suning/epps/sfeicuss/common/anticoncurrency/CallBack
  #127 = NameAndType        #177:#178     // process:()Ljava/lang/Object;
  #128 = NameAndType        #179:#180     // handlerIsSuccessOrNot:(Ljava/lang/Object;)Z
  #129 = Utf8               业务结果:{}
  #130 = Class              #181          // java/lang/Boolean
  #131 = NameAndType        #182:#183     // valueOf:(Z)Ljava/lang/Boolean;
  #132 = NameAndType        #175:#184     // debug:(Ljava/lang/String;Ljava/lang/Object;)V
  #133 = Utf8               java/lang/Exception
  #134 = Utf8               回调业务处理异常
  #135 = NameAndType        #185:#186     // error:(Ljava/lang/String;Ljava/lang/Throwable;)V
  #136 = Utf8               com/suning/epps/sfeicuss/common/exception/AppException
  #137 = Class              #187          // com/suning/epps/sfeicuss/common/enums/ResponseCode
  #138 = NameAndType        #188:#189     // ERROR:Lcom/suning/epps/sfeicuss/common/enums/ResponseCode;
  #139 = NameAndType        #190:#168     // getCode:()Ljava/lang/String;
  #140 = NameAndType        #64:#191      // "<init>":(Ljava/lang/String;Ljava/lang/String;)V
  #141 = NameAndType        #192:#193     // putBeanObj:(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;
  #142 = Utf8               true
  #143 = NameAndType        #194:#170     // del:(Ljava/lang/String;)Ljava/lang/Long;
  #144 = NameAndType        #195:#196     // publish:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Long;
  #145 = NameAndType        #197:#198     // subscribe:(Ljava/lang/String;)Ljava/lang/String;
  #146 = Class              #161          // java/lang/String
  #147 = NameAndType        #199:#180     // equals:(Ljava/lang/Object;)Z
  #148 = NameAndType        #200:#201     // getBeanObj:(Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;
  #149 = Utf8               收到订阅消息:{}
  #150 = NameAndType        #202:#203     // handlerResult:(Ljava/lang/Object;)Ljava/lang/Object;
  #151 = Class              #204          // java/lang/ThreadLocal
  #152 = NameAndType        #205:#178     // get:()Ljava/lang/Object;
  #153 = Utf8               java/lang/Integer
  #154 = NameAndType        #206:#207     // intValue:()I
  #155 = NameAndType        #71:#72       // execute:(Ljava/lang/String;Ljava/lang/Class;ILcom/suning/epps/sfeicuss/common/anticoncurrency/CallBack;)Ljava/lang/Object;
  #156 = Utf8               超过重试次数
  #157 = NameAndType        #64:#176      // "<init>":(Ljava/lang/String;)V
  #158 = Class              #208          // org/slf4j/LoggerFactory
  #159 = NameAndType        #209:#210     // getLogger:(Ljava/lang/Class;)Lorg/slf4j/Logger;
  #160 = Utf8               java/lang/Object
  #161 = Utf8               java/lang/String
  #162 = Utf8               java/lang/Class
  #163 = Utf8               com/suning/epps/sfeicuss/common/anticoncurrency/CallBack
  #164 = Utf8               (Lcom/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe;)V
  #165 = Utf8               append
  #166 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #167 = Utf8               toString
  #168 = Utf8               ()Ljava/lang/String;
  #169 = Utf8               com/suning/epps/sfeicuss/common/util/RedisClientUtils
  #170 = Utf8               (Ljava/lang/String;)Ljava/lang/Long;
  #171 = Utf8               java/lang/Long
  #172 = Utf8               longValue
  #173 = Utf8               ()J
  #174 = Utf8               org/slf4j/Logger
  #175 = Utf8               debug
  #176 = Utf8               (Ljava/lang/String;)V
  #177 = Utf8               process
  #178 = Utf8               ()Ljava/lang/Object;
  #179 = Utf8               handlerIsSuccessOrNot
  #180 = Utf8               (Ljava/lang/Object;)Z
  #181 = Utf8               java/lang/Boolean
  #182 = Utf8               valueOf
  #183 = Utf8               (Z)Ljava/lang/Boolean;
  #184 = Utf8               (Ljava/lang/String;Ljava/lang/Object;)V
  #185 = Utf8               error
  #186 = Utf8               (Ljava/lang/String;Ljava/lang/Throwable;)V
  #187 = Utf8               com/suning/epps/sfeicuss/common/enums/ResponseCode
  #188 = Utf8               ERROR
  #189 = Utf8               Lcom/suning/epps/sfeicuss/common/enums/ResponseCode;
  #190 = Utf8               getCode
  #191 = Utf8               (Ljava/lang/String;Ljava/lang/String;)V
  #192 = Utf8               putBeanObj
  #193 = Utf8               (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;
  #194 = Utf8               del
  #195 = Utf8               publish
  #196 = Utf8               (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Long;
  #197 = Utf8               subscribe
  #198 = Utf8               (Ljava/lang/String;)Ljava/lang/String;
  #199 = Utf8               equals
  #200 = Utf8               getBeanObj
  #201 = Utf8               (Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;
  #202 = Utf8               handlerResult
  #203 = Utf8               (Ljava/lang/Object;)Ljava/lang/Object;
  #204 = Utf8               java/lang/ThreadLocal
  #205 = Utf8               get
  #206 = Utf8               intValue
  #207 = Utf8               ()I
  #208 = Utf8               org/slf4j/LoggerFactory
  #209 = Utf8               getLogger
  #210 = Utf8               (Ljava/lang/Class;)Lorg/slf4j/Logger;
{
  public com.suning.epps.sfeicuss.common.anticoncurrency.PublishAndSubscribe();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=4, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: new           #2                  // class com/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe$1
         8: dup
         9: aload_0
        10: invokespecial #3                  // Method com/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe$1."<init>":(Lcom/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe;)V
        13: putfield      #4                  // Field threadLocal:Ljava/lang/ThreadLocal;
        16: return
      LineNumberTable:
        line 28: 0
        line 60: 4
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      17     0  this   Lcom/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe;

  public <T extends java.lang.Object> T execute(java.lang.String, java.lang.Class<T>, int, com.suning.epps.sfeicuss.common.anticoncurrency.CallBack);
    descriptor: (Ljava/lang/String;Ljava/lang/Class;ILcom/suning/epps/sfeicuss/common/anticoncurrency/CallBack;)Ljava/lang/Object;
    flags: ACC_PUBLIC
    Code:
      stack=5, locals=13, args_size=5
         0: aconst_null
         1: astore        5
         3: new           #5                  // class java/lang/StringBuilder
         6: dup
         7: invokespecial #6                  // Method java/lang/StringBuilder."<init>":()V
        10: ldc           #8                  // String PUBANDSUB_KEY_
        12: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        15: aload_1
        16: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        19: invokevirtual #10                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        22: astore        6
        24: new           #5                  // class java/lang/StringBuilder
        27: dup
        28: invokespecial #6                  // Method java/lang/StringBuilder."<init>":()V
        31: ldc           #11                 // String PUB_KEY
        33: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        36: aload_1
        37: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        40: invokevirtual #10                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        43: astore        7
        45: iload_3
        46: iconst_1
        47: if_icmpge     52
        50: iconst_3
        51: istore_3
        52: aload         6
        54: invokestatic  #12                 // Method com/suning/epps/sfeicuss/common/util/RedisClientUtils.incr:(Ljava/lang/String;)Ljava/lang/Long;
        57: invokevirtual #13                 // Method java/lang/Long.longValue:()J
        60: lstore        8
        62: getstatic     #14                 // Field LOGGER:Lorg/slf4j/Logger;
        65: ldc           #15                 // String 抢占到资源
        67: invokeinterface #16,  2           // InterfaceMethod org/slf4j/Logger.debug:(Ljava/lang/String;)V
        72: iconst_0
        73: istore        10
        75: lload         8
        77: lconst_1
        78: lcmp
        79: ifne          195
        82: ldc           #17                 // String false
        84: astore        11
        86: aload         4
        88: invokeinterface #18,  1           // InterfaceMethod com/suning/epps/sfeicuss/common/anticoncurrency/CallBack.process:()Ljava/lang/Object;
        93: astore        5
        95: aload         4
        97: aload         5
        99: invokeinterface #19,  2           // InterfaceMethod com/suning/epps/sfeicuss/common/anticoncurrency/CallBack.handlerIsSuccessOrNot:(Ljava/lang/Object;)Z
       104: istore        10
       106: getstatic     #14                 // Field LOGGER:Lorg/slf4j/Logger;
       109: ldc           #20                 // String 业务结果:{}
       111: iload         10
       113: invokestatic  #21                 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
       116: invokeinterface #22,  3           // InterfaceMethod org/slf4j/Logger.debug:(Ljava/lang/String;Ljava/lang/Object;)V
       121: goto          154
       124: astore        12
       126: getstatic     #14                 // Field LOGGER:Lorg/slf4j/Logger;
       129: ldc           #24                 // String 回调业务处理异常
       131: aload         12
       133: invokeinterface #25,  3           // InterfaceMethod org/slf4j/Logger.error:(Ljava/lang/String;Ljava/lang/Throwable;)V
       138: new           #26                 // class com/suning/epps/sfeicuss/common/exception/AppException
       141: dup
       142: ldc           #24                 // String 回调业务处理异常
       144: getstatic     #27                 // Field com/suning/epps/sfeicuss/common/enums/ResponseCode.ERROR:Lcom/suning/epps/sfeicuss/common/enums/ResponseCode;
       147: invokevirtual #28                 // Method com/suning/epps/sfeicuss/common/enums/ResponseCode.getCode:()Ljava/lang/String;
       150: invokespecial #29                 // Method com/suning/epps/sfeicuss/common/exception/AppException."<init>":(Ljava/lang/String;Ljava/lang/String;)V
       153: athrow
       154: iload         10
       156: ifeq          171
       159: aload         7
       161: aload         5
       163: invokestatic  #30                 // Method com/suning/epps/sfeicuss/common/util/RedisClientUtils.putBeanObj:(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;
       166: pop
       167: ldc           #31                 // String true
       169: astore        11
       171: aload         6
       173: invokestatic  #32                 // Method com/suning/epps/sfeicuss/common/util/RedisClientUtils.del:(Ljava/lang/String;)Ljava/lang/Long;
       176: invokevirtual #13                 // Method java/lang/Long.longValue:()J
       179: lconst_1
       180: lcmp
       181: ifne          192
       184: aload         6
       186: aload         11
       188: invokestatic  #33                 // Method com/suning/epps/sfeicuss/common/util/RedisClientUtils.publish:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Long;
       191: pop
       192: aload         5
       194: areturn
       195: aload         6
       197: invokestatic  #34                 // Method com/suning/epps/sfeicuss/common/util/RedisClientUtils.subscribe:(Ljava/lang/String;)Ljava/lang/String;
       200: astore        11
       202: getstatic     #14                 // Field LOGGER:Lorg/slf4j/Logger;
       205: ldc           #35                 // String subMsg
       207: aload         11
       209: invokeinterface #22,  3           // InterfaceMethod org/slf4j/Logger.debug:(Ljava/lang/String;Ljava/lang/Object;)V
       214: ldc           #31                 // String true
       216: aload         11
       218: invokevirtual #36                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
       221: ifeq          254
       224: aload         7
       226: aload_2
       227: invokestatic  #37                 // Method com/suning/epps/sfeicuss/common/util/RedisClientUtils.getBeanObj:(Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;
       230: astore        5
       232: getstatic     #14                 // Field LOGGER:Lorg/slf4j/Logger;
       235: ldc           #38                 // String 收到订阅消息:{}
       237: aload         5
       239: invokeinterface #22,  3           // InterfaceMethod org/slf4j/Logger.debug:(Ljava/lang/String;Ljava/lang/Object;)V
       244: aload         4
       246: aload         5
       248: invokeinterface #39,  2           // InterfaceMethod com/suning/epps/sfeicuss/common/anticoncurrency/CallBack.handlerResult:(Ljava/lang/Object;)Ljava/lang/Object;
       253: areturn
       254: aload_0
       255: getfield      #4                  // Field threadLocal:Ljava/lang/ThreadLocal;
       258: invokevirtual #40                 // Method java/lang/ThreadLocal.get:()Ljava/lang/Object;
       261: checkcast     #41                 // class java/lang/Integer
       264: invokevirtual #42                 // Method java/lang/Integer.intValue:()I
       267: istore        12
       269: iload         12
       271: iload_3
       272: if_icmpge     288
       275: iinc          12, 1
       278: aload_0
       279: aload_1
       280: aload_2
       281: iload_3
       282: aload         4
       284: invokevirtual #43                 // Method execute:(Ljava/lang/String;Ljava/lang/Class;ILcom/suning/epps/sfeicuss/common/anticoncurrency/CallBack;)Ljava/lang/Object;
       287: areturn
       288: new           #26                 // class com/suning/epps/sfeicuss/common/exception/AppException
       291: dup
       292: ldc           #44                 // String 超过重试次数
       294: invokespecial #45                 // Method com/suning/epps/sfeicuss/common/exception/AppException."<init>":(Ljava/lang/String;)V
       297: athrow
      Exception table:
         from    to  target type
            86   121   124   Class java/lang/Exception
      LineNumberTable:
        line 78: 0
        line 79: 3
        line 80: 24
        line 81: 45
        line 83: 50
        line 86: 52
        line 87: 62
        line 88: 72
        line 89: 75
        line 90: 82
        line 93: 86
        line 94: 95
        line 95: 106
        line 99: 121
        line 96: 124
        line 97: 126
        line 98: 138
        line 100: 154
        line 102: 159
        line 103: 167
        line 105: 171
        line 106: 184
        line 108: 192
        line 110: 195
        line 111: 202
        line 112: 214
        line 113: 224
        line 114: 232
        line 115: 244
        line 119: 254
        line 120: 269
        line 121: 275
        line 122: 278
        line 124: 288
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
          126      28    12     e   Ljava/lang/Exception;
           86     109    11   msg   Ljava/lang/String;
          269      29    12  time   I
          202      96    11 subMsg   Ljava/lang/String;
            0     298     0  this   Lcom/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe;
            0     298     1   key   Ljava/lang/String;
            0     298     2 clazz   Ljava/lang/Class;
            0     298     3 retryTime   I
            0     298     4 callBack   Lcom/suning/epps/sfeicuss/common/anticoncurrency/CallBack;
            3     295     5 result   Ljava/lang/Object;
           24     274     6 pasKey   Ljava/lang/String;
           45     253     7 pubKey   Ljava/lang/String;
           62     236     8  incr   J
           75     223    10  flag   Z
      LocalVariableTypeTable:
        Start  Length  Slot  Name   Signature
            0     298     2 clazz   Ljava/lang/Class<TT;>;
            3     295     5 result   TT;
      StackMapTable: number_of_entries = 8
        frame_type = 254 /* append */
          offset_delta = 52
          locals = [ class java/lang/Object, class java/lang/String, class java/lang/String ] frame_type = 255 /* full_frame */ offset_delta = 71 locals = [ class com/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe, class java/lang/String, class java/lang/Class, int, class com/suning/epps/sfeicuss/common/anticoncurrency/CallBack, class java/lang/Object, class java/lang/String, class java/lang/String, long, int, class java/lang/String ] stack = [ class java/lang/Exception ] frame_type = 29 /* same */ frame_type = 16 /* same */ frame_type = 20 /* same */ frame_type = 250 /* chop */ offset_delta = 2 frame_type = 252 /* append */ offset_delta = 58 locals = [ class java/lang/String ] frame_type = 252 /* append */ offset_delta = 33 locals = [ int ] Signature: #102 // <T:Ljava/lang/Object;>(Ljava/lang/String;Ljava/lang/Class<TT;>;ILcom/suning/epps/sfeicuss/common/anticoncurrency/CallBack;)TT; static {}; descriptor: ()V flags: ACC_STATIC Code: stack=1, locals=0, args_size=0 0: ldc #7 // class com/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe 2: invokestatic #46 // Method org/slf4j/LoggerFactory.getLogger:(Ljava/lang/Class;)Lorg/slf4j/Logger; 5: putstatic #14 // Field LOGGER:Lorg/slf4j/Logger; 8: return LineNumberTable: line 30: 0 } SourceFile: "PublishAndSubscribe.java" RuntimeVisibleAnnotations: 0: #107() InnerClasses: #2; //class com/suning/epps/sfeicuss/common/anticoncurrency/PublishAndSubscribe$1