编译的.class文件,可以用javap进行反编译

javap Test.class

javap -c Test.class

javap -verbose Test.class

1、创建MyTest1.java

public class MyTest1 {
private int a = 1; public MyTest1() {
} public int getA() {
return this.a;
} public void setA(int a) {
this.a = a;
}
}

使用D:\workspace\study\ jvm_demo\build\classes\java\main\com\example\jvm\bytecode>javap -verbose  MyTest1.class

Classfile /D:/workspace/study/ jvm_demo/build/classes/java/main/com/example/jvm/bytecode/MyTest1.class
Last modified 2019-6-23; size 495 bytes
MD5 checksum 54c0850cfabb7f115919c93e556e3630
Compiled from "MyTest1.java"
public class com.example.jvm.bytecode.MyTest1
SourceFile: "MyTest1.java"
minor version: 0
major version: 51
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #4.#20 // java/lang/Object."<init>":()V
#2 = Fieldref #3.#21 // com/example/jvm/bytecode/MyTest1.a:I
#3 = Class #22 // com/example/jvm/bytecode/MyTest1
#4 = Class #23 // java/lang/Object
#5 = Utf8 a
#6 = Utf8 I
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 Lcom/example/jvm/bytecode/MyTest1;
#14 = Utf8 getA
#15 = Utf8 ()I
#16 = Utf8 setA
#17 = Utf8 (I)V
#18 = Utf8 SourceFile
#19 = Utf8 MyTest1.java
#20 = NameAndType #7:#8 // "<init>":()V
#21 = NameAndType #5:#6 // a:I
#22 = Utf8 com/example/jvm/bytecode/MyTest1
#23 = Utf8 java/lang/Object
{
public com.example.jvm.bytecode.MyTest1();
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: iconst_1
6: putfield #2 // Field a:I
9: return
LineNumberTable:
line 6: 0
line 8: 4
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 this Lcom/example/jvm/bytecode/MyTest1; public int getA();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: getfield #2 // Field a:I
4: ireturn
LineNumberTable:
line 12: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/example/jvm/bytecode/MyTest1; public void setA(int);
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: iload_1
2: putfield #2 // Field a:I
5: return
LineNumberTable:
line 16: 0
line 17: 5
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this Lcom/example/jvm/bytecode/MyTest1;
0 6 1 a I
}

  

2、使用WinHex打开MyTest1.class文件

1、使用javap -verbose命令分析一个字节码文件时,将会分析该字节码文件的魔数、版本号、常量池、类的构造方法、类中的方法信息、类变量与成员变量等信息。
2、魔数: 所有的.class字节码文件的前4个字节都是魔数,魔数值为固定值: 0xCAFEBABE.
3、魔数之后的四个字节为版本信息,前两个字节表示minor version(次版本号),后两个字节表示major version(主版本号)。这里的版本号为 00 00 00 33,换算成十进制,表示次版本为0,主版本为51. (51代表JDK7). 所有该文件的版本号为: 1.7.0
4、常量池(constant pool): 紧接着主版本号之后的就是常量池入口。一个Java类中定义的很多信息都是由常量池来维护和描述的,可以将常量池看作是Class文件的资源仓库,比如说Java类中定义的方法与变量信息,都是存储在常量池中。常量池主要存储两类常量: 字面量与符号引用。字面量如文本字符串,Java中声明为final的 常量值等,而符号引用如类和接口的全局限定名,字段的名称和描述符,方法的名称和描述符等。
5、常量池的总体结构: Java类所对应常量池主要由常量池数量与常量池数组(常量表)这两部分共同构成。常量池数量紧跟在主版本号后面,占据2个字节; 常量池数组则紧跟在常量池数量之后。常量池数组与一般的数组不同的是,常量池数组中不同的元素的类型、结构都是不同的,长度当然也是不同; 但是,每一种元素的第一个数据都是一个u1类型,该字节是标志位,占据1个字节。JVM在解析常量池时,会根据这个u1类型来获取元素的具体类型。值得注意的是,常量池数组中元素的个数 = 常量池数 - 1 (其中0暂时不使用), 目的是满足某些常量池索引值的数据在特定情况下需要表单[不引用任何一个常量池]的含义 ; 根本原因在于,索引为0也是一个常量(保留常量),只不过它不位于常量表中,这个常量就对应null值; 所以常量池的索引从1而非0开始。
6、在JVM规范中,每个变量/字段都有描述信息,描述信息主要的作用是描述字段的数据类型、方法的参数列表(包括数量、类型与顺序)与返回值。根据描述规则,基本数据类型和代表无返回值的void类型都用一个大写字符来表示,对象类型则使用字符L加对象的全限定名称来表示。为了压缩字节码文件的体积,对于基本数据类型,JVM都只使用一个大写字母来表示,如下所示B - byte, C - char, D - double, F - float, I - int, J - long, S - short, Z -boolean, V -void, L -对象类型, 如Ljava/lang/String;
7、对于数组来说,每一个维度使用一个前置的[来表示,如int[]被记录为[I, String[][]被记录为[[Ljava/lang/String
8、用描述符描述方法时,按照先参数列表,后返回值的顺序来描述。参数列表按照参数的严格顺序放在一组()之内,如方法String getRealnamebyIdAndNickname(int id, String name)的描述符为:(I,Ljava/lang/String;) Ljava/lang/String;

3、Class文件结构中常量池中11种数据类型的结构总表

上面的表中描述了11中数据类型的结构,其实在jdk1.7之后又增加了3种

CONSTANT_MethodHandle_info, CONSTANT_MethodType_info 以及CONSTANT_InvokeDynamic_info) 这样总共14种。

4、Java字节码整体结构

Access_Flag访问标志: 访问标志信息包括该Class文件是类还是接口,是否被定义成public,是否是abstract,如果是类,是否被声明成final。通过上面的MyTest1源代码,我们知道该文件是类并且是public。

0x 00 21: 是0x 0020 和 0x0001的并集,表示ACC_PUBLIC与ACC_SUPER

Fields字段表集合: 字段表用于描述类和接口中声明的变量。这里的字段包含了类级别变量(静态变量)以及实例变量(成员变量),但是不包含方法内声明的局部变量

 字段表结构

 field_info

5、Java字节码整体结构

在Class文件的定义

6、Class字节码中有两种数据类型

1)字节数据直接量: 这是基本的数据类型。共细分为u1,u2,u4,u8四种,分别代表连续的1个字节,2个字节,4个字节,8个字节组成的整体数据。

2)表(数组): 表是由多个基本数据或其它表,按照既定顺序组成的大的数据集合。表是有结构的,它的结构体现在: 组成表的成分所在的位置和顺序都是已经严格定义好的。

JVM 字节码的结构的更多相关文章

  1. JVM 字节码执行实例分析

    前言 最近在看<Java 虚拟机规范>和<深入理解JVM虚拟机>,对于字节码的执行有了进一步的了解.字节码就像是汇编语言,是 JVM 的指令集.下面我们先对 JVM 执行引擎做 ...

  2. Java finally语句到底是在return之前还是之后执行(JVM字节码分析及内部体系结构)?

    之前看了一篇关于"Java finally语句到底是在return之前还是之后执行?"这样的博客,看到兴致处,突然博客里的一个测试用例让我产生了疑惑. 测试用例如下: public ...

  3. JVM 字节码(三)异常在字节码中的处理(catch 和 throws)

    JVM 字节码(三)异常在字节码中的处理(catch 和 throws) 在 ClassFile 中到底是如何处理异常的呢? 一.代码块异常 catch catch 中的异常代码块在异常是如何处理的呢 ...

  4. JVM 字节码(二)方法表详解

    JVM 字节码(二)方法表和属性表 上一节中对 ClassFile 的整体进行了五个详细的说明, 本节围绕 ClassFile 最重要的一个内容 - 方法表的 Code 属性展开 ,更多 JVM Me ...

  5. JVM 字节码(一)字节码规范

    JVM 字节码(一)字节码规范 JVM 学习资源 Java ClassFile 字节码规范(Oracle) Java 虚拟机规范(Java SE 7 中文版) (周志明等译) Java 反编译工具 - ...

  6. JVM总结(五):JVM字节码执行引擎

    JVM字节码执行引擎 运行时栈帧结构 局部变量表 操作数栈 动态连接 方法返回地址 附加信息 方法调用 解析 分派 –“重载”和“重写”的实现 静态分派 动态分派 单分派和多分派 JVM动态分派的实现 ...

  7. class字节码的结构

    class字节码的结构 使用javap -verbose 命令分析一个.class字节码文件时(以下简称字节码文件),将会分析该字节码文件的魔数,版本号,常量池,类信息,类的构造方法,类中的方法信息, ...

  8. 一夜搞懂 | JVM 字节码执行引擎

    前言 本文已经收录到我的 Github 个人博客,欢迎大佬们光临寒舍: 我的 GIthub 博客 学习导图 一.为什么要学习字节码执行引擎? 代码编译的结果从本地机器码转变为字节码,是存储格式发展的一 ...

  9. 初探JVM字节码

    作者: LemonNan 原文地址: https://juejin.im/post/6885658003811827725 代码地址: https://github.com/LemonLmNan/By ...

随机推荐

  1. WinServer-文件共享端口

    When turning on Firewall, please assure that “File and Printer Sharing” on current network profile i ...

  2. 解决通过vue-router打开tab页,下次进入还是上次history缓存的界面状态的问题

    一.问题描述: 1. 跳转模式:界面A-->界面B(界面A中通过 this.$router.push({name:'组件B名称', params: {参数}}) 通过打开新tab页的方式打开界面 ...

  3. HTML&CSS基础-外边框

    HTML&CSS基础-外边框  作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.HTML <!DOCTYPE html> <html> <h ...

  4. CCS设置第一个li的元素与其他li样式不同

    <div class="ly-content-list"> <ul> <li> <div class="title"& ...

  5. Java并发(九)【转载】不可不说的Java“锁”事

    转载自 美团技术团队,原文链接 不可不说的Java“锁”事 前言 Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率.本文旨在对锁相关源码(本文中的源码来自JDK ...

  6. java中的String要点解析

    String类使我们经常使用的一个类,经常用来表示字符串常量. 字符串一旦被创建赋值,就不能被改变,因为String 底层是数组实现的,且被定义成final类型.我们可以看String源码. /** ...

  7. Eclipse的tab键为4个空格完整方法 附:阿里代码开发规范书

    开发规范书:http://pan.baidu.com/s/1dESdyox 1.点击 window->preference-,依次选择 General->Editors->Text ...

  8. 洛谷-P2661 信息传递——有向图中的最小环

    题意 给定一个 $n$ 个结点有向图,求其中最小环的大小.($n \leq 200000$). 分析 由于每条点出度都为1且满足传递性,可以用并查集做. 如果有一条从x到y的有向边,那么y就是x的父亲 ...

  9. MySQL 优化之EXPLAIN详解(执行计划)

    学习MySQL时我们都知道索引对于一个SQL的优化很重要,而EXPLAIN关键字在分析是否正确以及高效的增加了索引时起到关键性的作用. 这篇文章显示了如何调用“EXPLAIN”来获取关于查询执行计划的 ...

  10. Codeforces Round #609 (Div. 2) 【A,B,C】

    题意:给一个n<=1e7,找两个合数a和b使得a-b的差为n. 构造a=3n,b=2n,必含有公因子n,只有当n是1的时候是特例. #include<bits/stdc++.h> u ...