Java Class文件结构解析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 1.Class文件基本结构概述 Class文件是一组以8位字节为基础单位的二进制流,当遇到需要8位字节以上空间的数据项时,则会按照高位在前的方式分隔成若干个8位字节进行存储。 Class文件由无符号数和表构成。

1.Class文件基本结构概述

  • Class文件是一组以8位字节为基础单位的二进制流,当遇到需要8位字节以上空间的数据项时,则会按照高位在前的方式分隔成若干个8位字节进行存储。
  • Class文件由无符号数和表构成。
  • 无符号数:以u1、u2、u4、u8分别代表1个字节、2个字节、4个字节和8个字节的无符号数,可以用来描述数字、索引引用、数量值、按照UTF-8编码构成的字符串值。
  • 表:由多个无符号数或其他表作为数据项构成的复杂数据类型,所有表都习惯性地以“_info”结尾。
  • Class文件格式如下:image

2.Class文件示例

  • 源代码示例
//接口
package com.example.jacoco;

public interface Animal {
    
    public void eat();

}


//实现类
package com.example.jacoco;

public class Cat implements Animal {
    public static String type = "cat";
    public String name;
    
    @Override
    public void eat(){
        System.out.println("-----------eat-----------");

    }
    
    public String getName() {
        return name;
    }
}
  • class文件示例(16进制的class文件)
cafe babe 0000 0034 002d 0700 0201 0016
636f 6d2f 6578 616d 706c 652f 6a61 636f
636f 2f43 6174 0700 0401 0010 6a61 7661
2f6c 616e 672f 4f62 6a65 6374 0700 0601
0019 636f 6d2f 6578 616d 706c 652f 6a61
636f 636f 2f41 6e69 6d61 6c01 0004 7479
7065 0100 124c 6a61 7661 2f6c 616e 672f
5374 7269 6e67 3b01 0004 6e61 6d65 0100
083c 636c 696e 6974 3e01 0003 2829 5601
0004 436f 6465 0800 0e01 0003 6361 7409
0001 0010 0c00 0700 0801 000f 4c69 6e65
4e75 6d62 6572 5461 626c 6501 0012 4c6f
6361 6c56 6172 6961 626c 6554 6162 6c65
0100 063c 696e 6974 3e0a 0003 0015 0c00
1300 0b01 0004 7468 6973 0100 184c 636f
6d2f 6578 616d 706c 652f 6a61 636f 636f
2f43 6174 3b01 0003 6561 7409 001a 001c
0700 1b01 0010 6a61 7661 2f6c 616e 672f
5379 7374 656d 0c00 1d00 1e01 0003 6f75
7401 0015 4c6a 6176 612f 696f 2f50 7269
6e74 5374 7265 616d 3b08 0020 0100 192d
2d2d 2d2d 2d2d 2d2d 2d2d 6561 742d 2d2d
2d2d 2d2d 2d2d 2d2d 0a00 2200 2407 0023
0100 136a 6176 612f 696f 2f50 7269 6e74
5374 7265 616d 0c00 2500 2601 0007 7072
696e 746c 6e01 0015 284c 6a61 7661 2f6c
616e 672f 5374 7269 6e67 3b29 5601 0007
6765 744e 616d 6501 0014 2829 4c6a 6176
612f 6c61 6e67 2f53 7472 696e 673b 0900
0100 2a0c 0009 0008 0100 0a53 6f75 7263
6546 696c 6501 0008 4361 742e 6a61 7661
0021 0001 0003 0001 0005 0002 0009 0007
0008 0000 0001 0009 0008 0000 0004 0008
000a 000b 0001 000c 0000 0026 0001 0000
0000 0006 120d b300 0fb1 0000 0002 0011
0000 0006 0001 0000 0004 0012 0000 0002
0000 0001 0013 000b 0001 000c 0000 002f
0001 0001 0000 0005 2ab7 0014 b100 0000
0200 1100 0000 0600 0100 0000 0300 1200
0000 0c00 0100 0000 0500 1600 1700 0000
0100 1800 0b00 0100 0c00 0000 3700 0200
0100 0000 09b2 0019 121f b600 21b1 0000
0002 0011 0000 000a 0002 0000 0009 0008
000b 0012 0000 000c 0001 0000 0009 0016
0017 0000 0001 0027 0028 0001 000c 0000
002f 0001 0001 0000 0005 2ab4 0029 b000
0000 0200 1100 0000 0600 0100 0000 0e00
1200 0000 0c00 0100 0000 0500 1600 1700
0000 0100 2b00 0000 0200 2c
  • javap -v Cat.class输出的class的文件结构
  Last modified 2019-4-7; size 779 bytes
  MD5 checksum e33bee3260446d95b04b553983a2f3a1
  Compiled from "Cat.java"
public class com.example.jacoco.Cat implements com.example.jacoco.Animal
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Class              #2             // com/example/jacoco/Cat
   #2 = Utf8               com/example/jacoco/Cat
   #3 = Class              #4             // java/lang/Object
   #4 = Utf8               java/lang/Object
   #5 = Class              #6             // com/example/jacoco/Animal
   #6 = Utf8               com/example/jacoco/Animal
   #7 = Utf8               type
   #8 = Utf8               Ljava/lang/String;
   #9 = Utf8               name
  #10 = Utf8               <clinit>
  #11 = Utf8               ()V
  #12 = Utf8               Code
  #13 = String             #14            // cat
  #14 = Utf8               cat
  #15 = Fieldref           #1.#16         // com/example/jacoco/Cat.type:Ljava/lang/String;
  #16 = NameAndType        #7:#8          // type:Ljava/lang/String;
  #17 = Utf8               LineNumberTable
  #18 = Utf8               LocalVariableTable
  #19 = Utf8               <init>
  #20 = Methodref          #3.#21         // java/lang/Object."<init>":()V
  #21 = NameAndType        #19:#11        // "<init>":()V
  #22 = Utf8               this
  #23 = Utf8               Lcom/example/jacoco/Cat;
  #24 = Utf8               eat
  #25 = Fieldref           #26.#28        // java/lang/System.out:Ljava/io/PrintStream;
  #26 = Class              #27            // java/lang/System
  #27 = Utf8               java/lang/System
  #28 = NameAndType        #29:#30        // out:Ljava/io/PrintStream;
  #29 = Utf8               out
  #30 = Utf8               Ljava/io/PrintStream;
  #31 = String             #32            // -----------eat-----------
  #32 = Utf8               -----------eat-----------
  #33 = Methodref          #34.#36        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #34 = Class              #35            // java/io/PrintStream
  #35 = Utf8               java/io/PrintStream
  #36 = NameAndType        #37:#38        // println:(Ljava/lang/String;)V
  #37 = Utf8               println
  #38 = Utf8               (Ljava/lang/String;)V
  #39 = Utf8               getName
  #40 = Utf8               ()Ljava/lang/String;
  #41 = Fieldref           #1.#42         // com/example/jacoco/Cat.name:Ljava/lang/String;
  #42 = NameAndType        #9:#8          // name:Ljava/lang/String;
  #43 = Utf8               SourceFile
  #44 = Utf8               Cat.java
{
  public static java.lang.String type;
    descriptor: Ljava/lang/String;
    flags: ACC_PUBLIC, ACC_STATIC

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

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: ldc           #13                 // String cat
         2: putstatic     #15                 // Field type:Ljava/lang/String;
         5: return
      LineNumberTable:
        line 4: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature

  public com.example.jacoco.Cat();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #20                 // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/example/jacoco/Cat;

  public void eat();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #25                 // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #31                 // String -----------eat-----------
         5: invokevirtual #33                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 9: 0
        line 11: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  this   Lcom/example/jacoco/Cat;

  public java.lang.String getName();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #41                 // Field name:Ljava/lang/String;
         4: areturn
      LineNumberTable:
        line 14: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/example/jacoco/Cat;
}
SourceFile: "Cat.java"

3.魔数

  • 每个Class文件的头4个字节称为魔数(Magic Number)
  • 唯一作用是用于确定这个文件是否为一个能被虚拟机接受的Class文件。
  • Class文件魔数的值为0xCAFEBABE。如果一个文件不是以0xCAFEBABE开头,那它就肯定不是Java class文件。

4.版本号

紧接着魔数的4个字节是Class文件版本号,版本号又分为:

  • 次版本号(minor_version): 前2字节用于表示次版本号
  • 主版本号(major_version): 后2字节用于表示主版本号。

这个的版本号是随着jdk版本的不同而表示不同的版本范围的。Java的版本号是从45开始的。如果Class文件的版本号超过虚拟机版本,将被拒绝执行。

0X0034(对应十进制的50):JDK1.8
0X0033(对应十进制的50):JDK1.7
0X0032(对应十进制的50):JDK1.6
0X0031(对应十进制的49):JDK1.5  
0X0030(对应十进制的48):JDK1.4  
0X002F(对应十进制的47):JDK1.3  
0X002E(对应十进制的46):JDK1.2
ps:0X表示16进制

5.常量池

Java代码在进行Java编译的时候,并不像C和C++那样有"连接"这一步骤,而是在虚拟机加载Class文件的时候进行动态连接。也就是说,在Class文件中不会保存各个方法和字段的最终内存布局信息,因此这些字段和方法的符号引用不经过转换的话是无法被虚拟机使用的。当虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建时或运行时解析并翻译到具体的内存地址之中。

紧接着魔数与版本号之后的是常量池入口.常量池简单理解为class文件的资源从库

  • 是Class文件结构中与其它项目关联最多的数据类型
  • 是占用Class文件空间最大的数据项目之一
  • 是在文件中第一个出现的表类型数据项目

5.1.constant_pool_count:

  • 常量池中常量的数量是不固定的,所以在常量池的入口需要放置一项u2类型(占2字节)的数据,代表常量池容量计数值。
  • 本例为0x0016,转化为十进制为22,即说明常量池中有21个常量(只有常量池的计数是从1开始的,其它集合类型均从0开始),索引值为1~21。
  • 第0项常量具有特殊意义,如果某些指向常量池索引值的数据在特定情况下需要表达“不引用任何一个常量池项目”的含义,这种情况可以将索引值置为0来表示
  • 常量池之中主要存放两大类常量:

    • 字面量: 比较接近于Java语言层面的常量概念,如文本字符串、被声明为final的常量值等
    • 符号引用: 属于编译原理方面的概念,包括了下面三类常量:

      • 类和接口的全限定名
      • 字段的名称和描述符
      • 方法的名称和描述符

5.2.constant_pool:

  • 表类型数据集合,即常量池中每一项常量都是一个表
  • 共有14种(JDK1.7前只有11种)结构各不相同的表结构数据。这14种表都有一个共同的特点,即均由一个u1类型的标志位开始,可以通过这个标志位来判断这个常量属于哪种常量类型,常量类型及其数据结构如下表所示:2395997_dc9aafbf16055c31

6.access flag

在常量池结束之后,紧接着的两个字节代表訪问标志。用于识别一些类或者接口层次的访问信息。例如以下表所看到的:
image

依据上面的表格,Cat.java的访问标志0x0021= 0x0001 | 0x0020 =ACC_PUBLIC | ACC_SUPER

7.类索引、父类索引、接口索引集合

  • 这三项数据主要用于确定这个类的继承关系,其中类索引(this_class)和父类索引(super_class)都是一个u2类型的数据,而接口索引(interface)集合是一组u2类型的数据,(多实现单继承)。
  • 类索引(this_class),用于确定这个类的全限定名,占2字节
  • 父类索引(super_class),用于确定这个类父类的全限定名(Java语言不允许多重继承,故父类索引只有一个。除了java.lang.Object类之外所有类都有父类,故除了java.lang.Object类之外,所有类该字段值都不为0),占2字节
  • 接口索引计数器(interfaces_count),占2字节。如果该类没有实现任何接口,则该计数器值为0,并且后面的接口的索引集合将不占用任何字节,
  • 接口索引集合(interfaces),一组u2类型数据的集合。用来描述这个类实现了哪些接口,这些被实现的接口将按implements语句(如果该类本身为接口,则为extends语句)后的接口顺序从左至右排列在接口的索引集合中
  • this_class、super_class与interfaces按顺序排列在访问标志之后,它们中保存的索引值均指向常量池中一个CONSTANT_Class_info类型的常量,通过这个常量中保存的索引值可以找到定义在CONSTANT_Utf8_info类型的常量中的全限定名字符串

如示例中的

0001 -- this class index
0003 -- super class index
0001 -- interface count
0005 -- interfaces index 

8.字段表集合

  • fields_count:字段表计数器,即字段表集合中的字段表数据个数,占2字节。本测试类其值为0x0001,即只有一个字段表数据,也就是测试类中只包含一个变量(不算方法内部变量)
  • fields:字段表集合,一组字段表类型数据的集合。字段表用于描述接口或类中声明的变量,包括类级别(static)和实例级别变量,不包括在方法内部声明的变量
  • field表的结构:在Java中一般通过如下几项描述一个字段:字段作用域(public、protected、private修饰符)、是类级别变量还是实例级别变量(static修饰符)、可变性(final修饰符)、并发可见性(volatile修饰符)、可序列化与否(transient修饰符)、字段数据类型(基本类型、对象、数组)以及字段名称。在字段表中,变量修饰符使用标志位表示,字段数据类型和字段名称则引用常量池中常量表示。字段表包含的固定数据项到descriptor_index结束,之后跟随一个属性表集合用于存储一些附加信息。字段表的结构如下图 image
  • 字段表集合中不会列出从父类或父接口中继承的字段,但是可能列出原本Java代码之中不存在的字段,如:内部类为了保持对外部类的访问性,自动添加指向外部类实例的字段。Java语言中字段是不能重载的,2个字段无论数据类型、修饰符是否相同,都不能使用相同的名称;但是对于字节码,只要字段描述符不同,字段重名就是合法的。

8.1.字段的access flag:

字段修饰符放在access_flags中,占2字节。image

8.2.字段的name index:

name index表示的16进制的值为指向常量池的某一项常量,代表的字段的名称

8.3.字段的descriptor_index:

代表着字段的描述符。描述符的作用是用来描述字段的数据类型、方法的参数列表(包括数量、类型以及顺序)和返回值。image

8.4.attributes_count和attribute表

在descriptor_index之后会跟随0-n项额外信息,详见属性表

如示例中的


0002 -- feild count

0009 -- access flag:public static 
0007 -- name index:type
0008 -- descript index: Ljava/lang/String;
0000 -- attribute_info:0

0001 -- access flag:public 
0009 -- name index:name
0008 -- descript index: Ljava/lang/String;
0000 -- attribute_info:0

9.方法表集合

  • methods_count:方法表计数器,即方法表集合中的方法表数据个数。占2字节,其值为0x0002,即测试类中有2个方法
  • methods:方法表集合,一组方法表类型数据的集合。方法表结构和字段表结构一样。image
  • method access flag:image
0004 -- method count
0008 -- access flag
000a -- name index
000b -- descript index
0001 -- attributes count

10.属性表集合

在Class文件、字段表和方法表都可以携带自己的属性信息,这个信息用属性表进行描述,用于描述某些场景专有的信息。

与Class文件中其它数据项对长度、顺序、格式的严格要求不同,属性表集合不要求其中包含的属性表具有严格的顺序,并且只要属性的名称不与已有的属性名称重复,任何人实现的编译器可以向属性表中写入自己定义的属性信息。虚拟机在运行时会忽略不能识别的属性,为了能正确解析Class文件,虚拟机规范中预定义了虚拟机实现必须能够识别的9项属性(预定义属性已经增加到21项)

10.1.常见的属性:

对于每个属性,它的名称需要从常量池中引用一个CONSTANT_utf8_info类型的常量类表示,而属性值的结构则是完全自定义的,只需要通过一个u4的长度属性区说明属性值所占用的位数即可.image

  • 属性表定义的结构:对于每个属性,它的名称需要从常量池中引用一个CONSTANT_utf8_info类型的常量类表示,而属性值的结构则是完全自定义的,只需要通过一个u4的长度属性区说明属性值所占用的位数即可.image

10.2.CODE属性:

Java程序方法体中的代码经过Javac编译处理后,最终变为字节码指令存储在Code属性中.Code属性出现在方法表的属性集合中,但是并非所有的方法表都有这个属性.例如接口或类中的方法就不存在Code属性了.在字节码指令之后的是方法的是方法的显式异常处理表集合,异常表对于Code属性来说并不是必须参在的.

  • code属性的结构:image
  • attribute_name_index是一项指向CONSTANT_Utf8_info型常量的索引,常量值固定为“Code”,他代表了该属性的属性名称,
  • attribute_length指示了属性值的长度,由于属性名称索引与属性长度一共为6个字节,所以属性值的长度固定为整个属性表长度减少6个字节。
  • max_stack代表了操作数栈(Operand Stacks)深度的最大值。在方法执行的任意时刻,操作数栈都不会超过这个深度。虚拟机运行的时候需要根据这个值分配栈帧(Stack Frame)中的操作帧深度。
  • max_locals代表了局部变量表所需的存储空间。在这里,max_locals的单位是Slot,Slot是虚拟机为局部变量分配内存所使用的最小单位。对于byte、char、float、int、short、boolean和returnAddress等长度不超过32位的数据类型,每个局部变量占用1个Slot,而double和long这两种64位的数据类型则需要两个Slot来存放。方法参数(包括实例方法中的隐藏参数“this”)、显式异常处理器的参数(Exception Handler Parameter,就是try-catch语句中catch块所定义的异常)、方法体中定义的局部变量都需要使用局部变量表来存放。另外,并不是在方法中用到了多少个局部变量,就把这些局部变量所占Slot之和作为max_locals的值,原因是局部变量表中的Slot可以重用,当代码执行超出一个局部变量的作用域时,这个局部变量所占的Slot可以被其他局部变量所使用,Javac编译器会根据变量的作用域来分配Slot给各个变量使用,然后计算出max_locals的大小。
  • code_length和code用来存储java源程序编译后生成的字节码指令。code_length代表字节码长度,code是用于存储字节码指令的一系列字节流。既然叫字节码指令,那么每个指令就是一个u1类型的单字节,当虚拟机读取到code中的一个字节码时,就可以对应找出这个字节码代表的是什么指令,并且可以知道这条指令后面是否需要跟随参数,以及参数应当如何理解。我们知道一个u1数据类型的取值范围为0x00~0xFF,对应十进制的0~255,也就是一共可以表达256条指令,目前,Java虚拟机规范已经定义了其中约200条编码值对应的指令含义。关于code_length,有一件值得注意的事情,虽然他是一个u4类型的长度值,理论上最大值可以达到2的32次方减1,但是虚拟机规范中明确限制了一个方法不允许超过65535条字节码指令,即他实际只使用了u2的长度,如果超过这个限制,Javac编译器也会拒绝编译。一般来讲,编写Java代码时只要不是刻意去编写一个超长的方法来为难编译器,是不太可能超过这个最大值的限制。但是,某些特殊情况,例如在编译一个很复杂的JSP文件时,某些JSP编译器会把JSP内容和页面输出的信息归并于一个方法之中,就可能因为方法生成字节码超长的原因而导致编译失败。
  • exception_table_length和exception_info:exception_table_length是u2类型,2个字节。异常表对Code属性来说不是必须存在, 在本实例中为0x0000,说明不存在异常表。
  • attributes_count和attributes:为Code表中包含的其他属性,如: LineNumberTable属性,用于描述java源码行号和字节码行号之间的对应关系。 LocalVariableTable属性,用户描述栈中局部变量表中的变量和java源码中定义的变量的关系。 异常表的格式如下表所示,他包含4个字段,这些字段的含义为:如果当字节码在第start_pc行到end_pc行之间(不含第end_pc行)出现了类型为catch_type或者其子类的异常(catch_type为指向一个CONSTANT_Class_info型常量的索引),则转到第handler_pc行继续处理。当catch_type的值为0时,代表任意异常情况都需要转向到handler_pc处进行处理。image

10.3.Exceptions属性:

这里的Exceptions属性是在方法表与Code属性平级的一项属性。Exceptions属性的作用是列举出方法中可能抛出的受查异常(Checked Exceptions),也就是说方法描述时在throws关键字啊后面列举的异常。他的结构见下表。imageExceptions属性中的number_of_exceptions项表示方法可能抛出number_of_exceptions种受查异常,每一种受查异常使用一个exception_index_table项表示,exception_index_table是一个指向常量池中CONSTANT_Class_info型常量的索引,代表了该受查异常的类型。

10.4.LineNumberTable属性:

LineNumberTable是Code属性中的一个子属性,用来描述java源文件行号与字节码文件偏移量之间的对应关系。当程序运行抛出异常时,异常堆栈中显示出错的行号就是根据这个对应关系来显示的,它的结构如下:image

  • 其中line_number_info结构如下:image

10.5.LocalVariableTable属性:

也是Code属性中的一个子属性,用来描述栈帧的局部变量表中变量与java源码中变量的对应关系,其结构如下:image

  • 其中local_variable_info结构如下: image

    • start_pc和length属性分别代表了这个局部变量的生命周期开始地字节码偏移量及其作用范围覆盖的长度,两者结合起来就是这个局部变量在字节码之中的作用域范围。
    • name_index和descriptor_index都是指向常量池中CONSTANT_Utf8_info型常量的索引,分别代表了局部变量的名称以及这个局部变量的描述符。
    • index是这个局部变量在栈帧局部变量表中Slot的位置。当这个变量数据类型是 64位类型时(double和long),他占用的Slot为index和index+1两个。

10.6 其他属性:

参考https://blog.csdn.net/qq_35892775/article/details/85860479

10.7.属性表示例分析

如示例中的

0004 -- method count

0008 -- access flag
000a -- name index:<clinit>
000b -- descript index
0001 -- attributes count
000c -- attribute_name_index : 对应Code属性
0000 0026       --     attribute_length:38个字节
0001            --     max_stack
0000            --     max_locals
0000 0006       --     code_length
120d b300 0fb1  --     code:指令
0000            --  exception_table_length
0002            --     attributes_count
0011            --  attribute_name_index:LineNumberTable
0000 0006       --  line_number_table_length
0001            --  line_number_table
0000            --  start_pc:字节码偏移量
0004            --  line_number:java源文件行号
0012            --  attribute_name_index:LocalVariableTable
0000 0002       --  attribute_length
0000            --  local_variable_table_length

0001 -- access flag
0013 -- name index:<init>
000b -- descript index
0001 -- attributes count
000c -- attribute_name_index : 对应Code属性
0000 002f       --     attribute_length:47个字节
0001            --     max_stack 
0001            --     max_locals 
0000 0005       --     code_length 
2ab7 0014 b1    --     code:指令
0000            --  exception_table_length
0002            --     attributes_count
0011            --  attribute_name_index:LineNumberTable
0000 0006       --  line_number_table_length
0001            --  line_number_table
0000            --  start_pc:字节码偏移量
0003            --  line_number:java源文件行号
0012            --  attribute_name_index:LocalVariableTable
0000 000c       --  attribute_length
0001            --  local_variable_table_length
0000            --  start_pc
0005            --  length
0016            --  name_index
0017            --  descriptor_index
0000            --  index

00
0100 1800 0b00 0100 0c00 0000 3700 0200
0100 0000 09b2 0019 121f b600 21b1 0000
0002 0011 0000 000a 0002 0000 0009 0008
000b 0012 0000 000c 0001 0000 0009 0016
0017 0000 0001 0027 0028 0001 000c 0000
002f 0001 0001 0000 0005 2ab4 0029 b000
0000 0200 1100 0000 0600 0100 0000 0e00
1200 0000 0c00 0100 0000 0500 1600 1700
0000 0100 2b00 0000 0200 2c

Java字节码指令大全

SMP_3_00_

参考:https://blog.csdn.net/github_35983163/article/details/52945845
参考:http://www.blogjava.net/DLevin/archive/2011/09/05/358033.html

相关文章
|
3天前
|
存储 缓存 Java
Java 并发编程——volatile 关键字解析
本文介绍了Java线程中的`volatile`关键字及其与`synchronized`锁的区别。`volatile`保证了变量的可见性和一定的有序性,但不能保证原子性。它通过内存屏障实现,避免指令重排序,确保线程间数据一致。相比`synchronized`,`volatile`性能更优,适用于简单状态标记和某些特定场景,如单例模式中的双重检查锁定。文中还解释了Java内存模型的基本概念,包括主内存、工作内存及并发编程中的原子性、可见性和有序性。
Java 并发编程——volatile 关键字解析
|
17天前
|
Java
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
80 34
|
1天前
|
Java 数据库连接 Spring
反射-----浅解析(Java)
在java中,我们可以通过反射机制,知道任何一个类的成员变量(成员属性)和成员方法,也可以堆任何一个对象,调用这个对象的任何属性和方法,更进一步我们还可以修改部分信息和。
|
23天前
|
存储 算法 Java
Java内存管理深度解析####
本文深入探讨了Java虚拟机(JVM)中的内存分配与垃圾回收机制,揭示了其高效管理内存的奥秘。文章首先概述了JVM内存模型,随后详细阐述了堆、栈、方法区等关键区域的作用及管理策略。在垃圾回收部分,重点介绍了标记-清除、复制算法、标记-整理等多种回收算法的工作原理及其适用场景,并通过实际案例分析了不同GC策略对应用性能的影响。对于开发者而言,理解这些原理有助于编写出更加高效、稳定的Java应用程序。 ####
|
23天前
|
存储 监控 算法
Java虚拟机(JVM)垃圾回收机制深度解析与优化策略####
本文旨在深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法及参数调优方法。通过剖析垃圾回收的生命周期、内存区域划分以及GC日志分析,为开发者提供一套实用的JVM垃圾回收优化指南,助力提升Java应用的性能与稳定性。 ####
|
25天前
|
Java 数据库连接 开发者
Java中的异常处理机制:深入解析与最佳实践####
本文旨在为Java开发者提供一份关于异常处理机制的全面指南,从基础概念到高级技巧,涵盖try-catch结构、自定义异常、异常链分析以及最佳实践策略。不同于传统的摘要概述,本文将以一个实际项目案例为线索,逐步揭示如何高效地管理运行时错误,提升代码的健壮性和可维护性。通过对比常见误区与优化方案,读者将获得编写更加健壮Java应用程序的实用知识。 --- ####
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
76 2
|
2月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
79 0
|
2天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
2天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析

推荐镜像

更多