首页 > 编程语言 >Java中class文件结构分析一

Java中class文件结构分析一

时间:2024-08-13 10:24:09浏览次数:13  
标签:lang 文件 00 Java 常量 Utf8 61 65 class

一:源代码

package com.tuling.smlz.jvm.classbyatecode;

/**
 * Created by smlz on 2019/11/5.
 */
public class TulingByteCode {

    private String userName;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

二:通过我们javap -verbose TulingByteCode .class反编译

//表示我们通过反编译的来源是哪个字节码文件
Classfile /D:/work_space/idea_space/spring-cloud-source/tuling-jvm/target/classes/com/tuling/smlz/jvm/classbyatecode/TulingByteCode.class
  //最后修改日期;文件大小
  Last modified 2019-11-5; size 629 bytes
  //文件的md5值
  MD5 checksum a0a9c001787f00738627278b0946a388
  //.class文件是通过哪个源文件编译过来的
  Compiled from "TulingByteCode.java"
  //字节码的详细信息
public class com.tuling.smlz.jvm.classbyatecode.TulingByteCode
  //jdk的次版本号
  minor version: 0
  //jdk的主版本号
  major version: 52
  //访问权限
  flags: ACC_PUBLIC, ACC_SUPER
  //常量池
Constant pool:
   #1 = Methodref          #4.#21         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#22         // com/tuling/smlz/jvm/classbyatecode/TulingByteCode.userName:Ljava/lang/String;
   #3 = Class              #23            // com/tuling/smlz/jvm/classbyatecode/TulingByteCode
   #4 = Class              #24            // java/lang/Object
   #5 = Utf8               userName
   #6 = Utf8               Ljava/lang/String;
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/tuling/smlz/jvm/classbyatecode/TulingByteCode;
  #14 = Utf8               getUserName
  #15 = Utf8               ()Ljava/lang/String;
  #16 = Utf8               setUserName
  #17 = Utf8               (Ljava/lang/String;)V
  #18 = Utf8               MethodParameters
  #19 = Utf8               SourceFile
  #20 = Utf8               TulingByteCode.java
  #21 = NameAndType        #7:#8          // "<init>":()V
  #22 = NameAndType        #5:#6          // userName:Ljava/lang/String;
  #23 = Utf8               com/tuling/smlz/jvm/classbyatecode/TulingByteCode
  #24 = Utf8               java/lang/Object
{ 
  //构造方法
  public com.tuling.smlz.jvm.classbyatecode.TulingByteCode();
    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 6: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/tuling/smlz/jvm/classbyatecode/TulingByteCode;
  //get方法
  public java.lang.String getUserName();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #2                  // Field userName:Ljava/lang/String;
         4: areturn
      LineNumberTable:
        line 11: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/tuling/smlz/jvm/classbyatecode/TulingByteCode;
  //set方法
  public void setUserName(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #2                  // Field userName:Ljava/lang/String;
         5: return
      LineNumberTable:
        line 15: 0
        line 16: 5
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       6     0  this   Lcom/tuling/smlz/jvm/classbyatecode/TulingByteCode;
            0       6     1 userName   Ljava/lang/String;
    MethodParameters:
      Name                           Flags
      userName
}
SourceFile: "TulingByteCode.java"

三:class文件通过16进制查看器打开如下

通过16进制查看器打开的文件结构是一个当个字节来显示,因为一个16进制数可以通过4位来表示,一个字节8位可以表示二个16进制数

我们class文件结构图

Class文件结构参照表:

Class文件结构伪代码

3.1)我们通过javap -verbose来分析一个字节码的时候,将会分析字节码文件的魔数,主 次版本号,常量池,类信息,类的构造方法,类的中的方法信息,类变量与成员变量等信息.

魔数: 文件的开头的 四个字节 是固定 值位 0xCAFEBABE

3.2)次版本号(minor version):二个字节00 00 表示jdk的次版本号

3.3)主版本号(major version):二个字节 00 34 表示为jdk的主版本号,34对于10进制为52

那么52代表的是1.8,51代表的是1.7 等等一直类推下去

所以通过主次版本号来确定我们jdk的版本是1.8.0

3.4)常量池入口,占用二个字节,表示常量池中的个数=00 19 (25)-1=24个, 为啥需要-1,因为常量池中的第0个位置被我们的jvm占用了表示为null 所以我们通过编译出来的常量池索引是从1开始的.

Constant pool:
   #1 = Methodref          #4.#21         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#22         // com/tuling/smlz/jvm/classbyatecode/TulingByteCode.userName:Ljava/lang/String;
   #3 = Class              #23            // com/tuling/smlz/jvm/classbyatecode/TulingByteCode
   #4 = Class              #24            // java/lang/Object
   #5 = Utf8               userName
   #6 = Utf8               Ljava/lang/String;
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/tuling/smlz/jvm/classbyatecode/TulingByteCode;
  #14 = Utf8               getUserName
  #15 = Utf8               ()Ljava/lang/String;
  #16 = Utf8               setUserName
  #17 = Utf8               (Ljava/lang/String;)V
  #18 = Utf8               MethodParameters
  #19 = Utf8               SourceFile
  #20 = Utf8               TulingByteCode.java
  #21 = NameAndType        #7:#8          // "<init>":()V
  #22 = NameAndType        #5:#6          // userName:Ljava/lang/String;
  #23 = Utf8               com/tuling/smlz/jvm/classbyatecode/TulingByteCode
  #24 = Utf8               java/lang/Object

3.4.1)常量池结构表如图所示

u1,u2,u4,u8分别代表1个字节,2个字节,4个字节,8个字节的无符号数

3.4.2)我们的常量池可以看作我们的java class类的一个资源仓库(比如Java类定的方法和变量信息),我们后面的方法 类的信息的描述信息都是通过索引去常量池中获取。

1)常量池中主要存放二种常量,一种是字面量 一种是符号引用

3.4.3)在JVM规范中,每个字段或者变量都有描述信息,描述信息的主要作用是 数据类型,方法参数列表,返回值类型等.

1)基本参数类型和void类型都是用一个大写的字符来表示,对象类型是通过一个大写L加全类名表示,这么做的好处就是在保证jvm能读懂class文件的情况下尽量的压缩class文件体积.

基本数据类型表示:

B---->byte

C---->char

D---->double

F----->float

I------>int

J------>long

S------>short

Z------>boolean

V------->void

对象类型:

String------>Ljava/lang/String;(后面有一个分号)

对于数组类型: 每一个唯独都是用一个前置 [ 来表示

比如: int[] ------>[ I,

String [][]------>[[Ljava.lang.String;

2)用描述符来描述方法的,先参数列表,后返回值的格式,参数列表按照严格的顺序放在()中

比如源码 String getUserInfoByIdAndName(int id,String name) 的方法描述符号

(I,Ljava/lang/String;)Ljava/lang/String;

第1个常量池分析: 0A 00 04 00 15

0A:表示是常量池中的常量类型为方法引用

00 04二个字节表示的是是方法所在类 指向常量池的索引位置为#4,然后我们发现

#4的常量类型是Class,也是符号引用类型,指向常量池#24的位置,而#24是的常量池类型是字面量值为:java/lang/Object

00 15二个字节表示是方法的描述符,指向常量池索引#21的位置,我们发现#21的常量类型是"NameAndType类型"属于引用类型,指向常量池的#7 #8位置

#7常量类型是UTF-8类型属于字面量值为: 为构造方法

#8常量也是UTF-8类型的字面量值为:()V

所以常量池中的第一个常量是:java/lang/Object."":()V

画图分析:

第二个常量分析:09 00 03 00 16

09表示的是我们的 CONSTANT_Methodref_info 字段类型的常量

00 03表示的class_index 表示是常量池中第三个 为我们的class常量的索引位置

00 16:表示该字段的名称和类型 指向我们常量池中索引为22的位置

解释:03表示指向常量池第三个位置,我们发现第三个位子是Class类型的常量,03位置的常量池应用指向的是#23的位置,而我们的#23常量池类型是utf-8表示是字面量

值为:com/tuling/smlz/jvm/classbyatecode/TulingByteCode

#22为常量池类型的nameAndType类型,分别指向我们的常量池第#5(utf-8类型的常量)的位置表示我们的字段的名称userName,#6指向的是常量池第六个位置,类型是utf-8类型的值为:Ljava/lang/String;

第二个常量com/tuling/smlz/jvm/classbyatecode/TulingByteCode.userName:Ljava/lang/String;

画图分析:

第三个常量分析: 07 00 17

第一个字节:07表示的是 class_info符号引用类型的常量

第二三个字节: 00 17表示是指向常量池中索引为23的位置,#23的常量池类型是utf8字面量

那么utf8_info的结构如下:

第#23的常量的结构是

其中 01表示utf8_info的常量类型

00 31:表示后面跟着49个字节是字面量的值

01 00 31 63 6F 6D 2F 74 75 6C 69 6E 67 2F 73 6D 6C

7A 2F 6A 76 6D 2F 63 6C 61 73 73 62 79 61 74 65

63 6F 64 65 2F 54 75 6C 69 6E 67 42 79 74 65 43

6F 64 65

第四个常量分析: 07 00 18

第一个字节:07表示的是 class_info符号引用类型的常量

第二三个字节: 00 18表示是指向常量池中索引为24的位置,#24的常量池类型是utf8字面量

那么utf8_info的结构如下:

01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74

其中 01表示utf8_info的常量类型

00 10:表示后面跟着16个字节是字面量的值

6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74 字面量的值为:java/lang/Object

第五个常量: 01 00 08 75 73 65 72 4E 61 6D 65

01:tag位表示的是utf8类型的字面量常量

00 08二个字节表示的是字面量常量的长度为8 、

75 73 65 72 4E 61 6D 65 转为字符串为userName

第六个常量分析:01 00 12 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B

01:tag位表示的是utf8类型的字面量常量

00 12二个字节表示的是字面量常量的长度为18 、

4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 转为字符串为 Ljava/lang/String;

第七个常量分析:01 00 06 3C 69 6E 69 74 3E

01:tag位表示的是utf8类型的字面量常量

00 06二个字节表示的是字面量常量的长度为6

3C 69 6E 69 74 3E 转为字符串为

第八个常量分析:01 00 03 28 29 56

01:tag位表示的是utf8类型的字面量常量

00 03二个字节表示的是字面量常量的长度为3

28 29 56 转为字符串为 ()V

第九个常量分析:01 00 04 43 6F 64 65

01:tag位表示的是utf8类型的字面量常量

00 04二个字节表示的是字面量常量的长度为4

43 6F 64 65 转为字符串为 Code

第十个常量分析:01 00 0F 4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65

01:tag位表示的是utf8类型的字面量常量

00 0F二个字节表示的是字面量常量的长度为15

4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65 转为字符串为 LineNumberTable

表示这个是行号表

第11个常量:01 00 12 4C 6F 63 61 6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65

01:tag位表示的是utf8类型的字面量常量

00 12二个字节表示的是字面量常量的长度为18

4C 6F 63 61 6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 转为字符串为LocalVariableTable

表示这个是本地变量表

第12个常量: 01 00 04 74 68 69 73

01:tag位表示的是utf8类型的字面量常量

00 14二个字节表示的是字面量常量的长度为4

74 68 69 73 转为字符串为this

第13个常量:

01 00 33 4C 63 6F 6D 2F 74 75 6C 69 6E 67 2F 73 6D 6C 7A 2F 6A 76 6D 2F 63 6C 61 73 73 62 79 61 74 65 63 6F 64 65 2F 54 75 6C 69 6E 67 42 79 74 65 43 6F 64 65 3B

01:tag位表示的是utf8类型的字面量常量

00 33二个字节表示的是字面量常量的长度为51

4C 63 6F 6D 2F 74 75 6C 69 6E 67 2F 73 6D 6C 7A 2F 6A 76 6D 2F 63 6C 61 73 73 62 79 61 74 65 63 6F 64 65 2F 54 75 6C 69 6E 67 42 79 74 65 43 6F 64 65 3B

表示字符串: Lcom/tuling/smlz/jvm/classbyatecode/TulingByteCode;

第14个常量:01 00 0B 67 65 74 55 73 65 72 4E 61 6D 65

01:tag位表示的是utf8类型的字面量常量

00 0B 二个字节表示的是字面量常量的长度为11

67 65 74 55 73 65 72 4E 61 6D 65 表示的是字符串getUserName

第15个常量分析:01 00 14 28 29 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B

01:tag位表示的是utf8类型的字面量常量

00 14 二个字节表示的是字面量常量的长度为20

接下来20个字节: 28 29 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 表示字符串

()Ljava/lang/String;

第16个常量池分析: 01 00 0B 73 65 74 55 73 65 72 4E 61 6D 65

01:tag位表示的是utf8类型的字面量常量

00 0B 二个字节表示的是字面量常量的长度为11

接下来11个字节: 73 65 74 55 73 65 72 4E 61 6D 65 表示字符串 setUserName

 

未完待续,请看下一篇 《Java中class文件结构分析一》

标签:lang,文件,00,Java,常量,Utf8,61,65,class
From: https://blog.csdn.net/qq_36324341/article/details/141155819

相关文章

  • Java中class文件结构分析二
    第17个常量池:010015284C6A6176612F6C616E672F537472696E673B295601:tag位表示的是utf8类型的字面量常量0015二个字节表示的是字面量常量的长度为21接下来21个字节:284C6A6176612F6C616E672F537472696E673B2956表示字符串(......
  • Java网络编程——Cookie & Session
    cookie前面我们学习Okhttp3库可以调用API、抓取网页、下载文件。但是这些操作都是不要求登录的,如果API、网页、文件等内容要求登录才能访问,就需要学习新的cookie相关的知识了。下面以豆瓣为例,使用Java程序读取“我的豆瓣”页面内容,在此过程中熟悉运用cookie。所......
  • 发现敏感文件信息(web+google+github):网络安全案例研究
    第一部分:互联网第二部分:GitHub第三部分:GoogleDork结论作为一名安全研究人员,工作中最有意义的方面之一是发现和报告可能危及敏感信息的漏洞。在这篇博文中,将带大家了解最近在Web应用程序上发现的敏感文件信息、所使用的工具和技术以及保护敏感文件的重要性。免责声明:本博......
  • 关于linux共享文件夹等一些配置
    一,共享文件夹virtualBox+ubuntu16.04共享文件夹可以方便我们主机和虚拟机进行文件的传输1.虚拟机菜单栏点击设备安装增强功能2.增强功能安装完成以后再点击设备选择共享文件夹,添加共享文件夹,并勾选"自动挂载"和"固定分配"3.然后需要将当前用户添加到vboxsf组  使用命令:sudo......
  • Makefile 编译多级目录多个目标文件模板
    对于当前目录结构下的Makefile(基于图书管理系统).├──Makefile├──README.md├──bin│├──adminsys│└──usersys├──build│├──adminmain.o│├──generalcore.o│├──generalimpl.o│├──generalview.o│├──......
  • ntds.dit 文件是 Active Directory (AD) 的数据库文件,它使用了 Microsoft Jet 数据库
    ntds.dit是ActiveDirectory数据库文件,存储了所有域控制器的目录服务数据,如用户账户、组信息和计算机对象。ntds.dit文件的默认路径通常位于WindowsServer操作系统的以下位置:CopyCode%SystemRoot%\NTDS\ntds.dit具体的路径可能会因安装配置或操作系统版本而......
  • Redis流详解及Java实践
    Redis流详解及Java实践RedisStream概述基本概念使用场景RedisStream命令XADD-添加消息XRANGE-获取消息XREAD-读取消息XGROUP-操作消费者组XACK-确认消息代码示例实战案例示例1:日志收集系统生产者服务消费者服务示例2:消息队列生产者服务消费者服务示......
  • 11、java程序流程控制之三:循环结构(while循环)、循环结构(do-while循环)、break 与 co
    java程序流程控制之三:Ⅰ、循环结构:while循环1、while循环结构:其一、描述:其二、代码为:其三、截图为:Ⅱ、循环结构:do-while循环1、do-while循环结构:其一、描述:其二、代码为:其三、截图为:2、do-while循环结构的案例1:输出正数或负数的个数其一、描述:其二、代码为:其三、......
  • 【C#】实现读写文件
    ///<summary>///同步锁///</summary>privatestaticreadonlyobjectsyncRoot=newobject();///<summary>///读同步锁///</summary>privatestaticreadonlyobjectsyncReadRoot=newobject();///<summary>///覆盖写文件......
  • 开源的 P2P 跨平台传文件应用「GitHub 热点速览」
    就在上周,发完那篇文章之后不久,我就有幸获得了GitHubModels服务公测的访问权限,所以就体验了一下Playground聊天功能。起初,我以为这是“微软菩萨”降临,但玩了一圈下来,发现实际效果并没有那么惊艳,还没上周热门的开源项目有趣。例如,基于WebRTC的文件传输平台ShareDrop,只需......