热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

emjava_JVMjavap工具

javap是一个能够将class文件反汇编成人类可读格式的工具。publicclassFoo{privateinttryBlock;privateintcatchBlock;pri

javap 是一个能够将 class 文件反汇编成人类可读格式的工具。

public classFoo {private inttryBlock;private intcatchBlock;private intfinallyBlock;private intmethodExit;public voidtest() {try{

tryBlock= 0;

}catch(Exception e) {

catchBlock= 1;

}finally{

finallyBlock= 2;

}

methodExit= 3;

}

}

使用javap

$ javac Foo.java

$ javap-p -v Foo

Classfile ../Foo.classLast modified ..; size541bytes

MD5 checksum 3828cdfbba56fea1da6c8d94fd13b20d

Compiled from"Foo.java"

public classFoo

minor version:0major version:54flags: (0x0021) ACC_PUBLIC, ACC_SUPER

this_class: #7 //Foo

super_class: #8 //java/lang/Object

interfaces: 0, fields: 4, methods: 2, attributes: 1Constant pool:

#1 = Methodref #8.#23 //java/lang/Object."":()V

#2 = Fieldref #7.#24 //Foo.tryBlock:I

#3 = Fieldref #7.#25 //Foo.finallyBlock:I

#4 = Class #26 //java/lang/Exception

#5 = Fieldref #7.#27 //Foo.catchBlock:I

#6 = Fieldref #7.#28 //Foo.methodExit:I

#7 = Class #29 //Foo

#8 = Class #30 //java/lang/Object

#9 =Utf8 tryBlock

#10 =Utf8 I

#11 =Utf8 catchBlock

#12 =Utf8 finallyBlock

#13 =Utf8 methodExit

#14 = Utf8 #15 =Utf8 ()V

#16 =Utf8 Code

#17 =Utf8 LineNumberTable

#18 =Utf8 test

#19 =Utf8 StackMapTable

#20 = Class #31 //java/lang/Throwable

#21 =Utf8 SourceFile

#22 =Utf8 Foo.java

#23 = NameAndType #14:#15 //"":()V

#24 = NameAndType #9:#10 //tryBlock:I

#25 = NameAndType #12:#10 //finallyBlock:I

#26 = Utf8 java/lang/Exception

#27 = NameAndType #11:#10 //catchBlock:I

#28 = NameAndType #13:#10 //methodExit:I

#29 =Utf8 Foo

#30 = Utf8 java/lang/Object

#31 = Utf8 java/lang/Throwable

{private inttryBlock;

descriptor: I

flags: (0x0002) ACC_PRIVATEprivate intcatchBlock;

descriptor: I

flags: (0x0002) ACC_PRIVATEprivate intfinallyBlock;

descriptor: I

flags: (0x0002) ACC_PRIVATEprivate intmethodExit;

descriptor: I

flags: (0x0002) ACC_PRIVATEpublicFoo();

descriptor: ()V

flags: (0x0001) ACC_PUBLIC

Code:

stack=1, locals=1, args_size=1

0: aload_01: invokespecial #1 //Method java/lang/Object."":()V

4: returnLineNumberTable:

line1: 0

public voidtest();

descriptor: ()V

flags: (0x0001) ACC_PUBLIC

Code:

stack=2, locals=3, args_size=1

0: aload_01: iconst_02: putfield #2 //Field tryBlock:I

5: aload_06: iconst_27: putfield #3 //Field finallyBlock:I

10: goto 35

13: astore_114: aload_015: iconst_116: putfield #5 //Field catchBlock:I

19: aload_020: iconst_221: putfield #3 //Field finallyBlock:I

24: goto 35

27: astore_228: aload_029: iconst_230: putfield #3 //Field finallyBlock:I

33: aload_234: athrow35: aload_036: iconst_337: putfield #6 //Field methodExit:I

40: returnException table:

from to target type0 5 13 Class java/lang/Exception0 5 27any13 19 27any

LineNumberTable:

line9: 0line13: 5line14: 10line10: 13line11: 14line13: 19line14: 24line13: 27line14: 33line15: 35line16: 40StackMapTable: number_of_entries= 3frame_type= 77 /*same_locals_1_stack_item*/stack= [ class java/lang/Exception ]

frame_type= 77 /*same_locals_1_stack_item*/stack= [ class java/lang/Throwable ]

frame_type= 7 /*same*/}

SourceFile:"Foo.java"

这里面我用到了两个选项。第一个选项是 -p。默认情况下 javap 会打印所有非私有的字段和方法,当加了 -p 选项后,它还将打印私有的字段和方法。第二个选项是 -v。它尽可能地打印所有信息。如果你只需要查阅方法对应的字节码,那么可以用 -c 选项来替换 -v。

javap 的 -v 选项的输出分为几大块。

1. 基本信息,涵盖了原 class 文件的相关信息。

class 文件的版本号(minor version: 0,major version: 54),该类的访问权限(flags: (0x0021) ACC_PUBLIC, ACC_SUPER),该类(this_class: #7)以及父类(super_class: #8)的名字,所实现接口(interfaces: 0)、字段(fields: 4)、方法(methods: 2)以及属性(attributes: 1)的数目。

这里属性指的是 class 文件所携带的辅助信息,比如该 class 文件的源文件的名称。这类信息通常被用于 Java 虚拟机的验证和运行,以及 Java 程序的调试,一般无须深入了解。

Classfile ../Foo.classLast modified ..; size541bytes

MD5 checksum 3828cdfbba56fea1da6c8d94fd13b20d

Compiled from"Foo.java"

public classFoo

minor version:0major version:54flags: (0x0021) ACC_PUBLIC, ACC_SUPER

this_class: #7 //Foo

super_class: #8 //java/lang/Object

interfaces: 0, fields: 4, methods: 2, attributes: 1

class 文件的版本号指的是编译生成该 class 文件时所用的 JRE 版本。由较新的 JRE 版本中的 javac 编译而成的 class 文件,不能在旧版本的 JRE 上跑,否则,会出现如下异常信息。(Java 8 对应的版本号为 52,Java 10 对应的版本号为 54。)

Exception in thread "main" java.lang.UnsupportedClassVersionError: Foo has been compiled by a more recent version of the Java Runtime (class file version 54.0), this version of the Java Runtime only recognizes class file versions up to 52.0

类的访问权限通常为 ACC_ 开头的常量。具体每个常量的意义可以查阅 Java 虚拟机规范 4.1 小节 [1]。

2. 常量池,用来存放各种常量以及符号引用。

常量池中的每一项都有一个对应的索引(如 #1),并且可能引用其他的常量池项(#1 = Methodref #8.#23)。

Constant pool:

#1 = Methodref #8.#23 //java/lang/Object."":()V

...

#8 = Class #30 //java/lang/Object

...

#14 = Utf8 #15 =Utf8 ()V

...

#23 = NameAndType #14:#15 //"":()V

...

#30 = Utf8 java/lang/Object

3. 字段区域,用来列举该类中的各个字段。

这里最主要的信息便是该字段的类型(descriptor: I)以及访问权限(flags: (0x0002) ACC_PRIVATE)。对于声明为 final 的静态字段而言,如果它是基本类型或者字符串类型,那么字段区域还将包括它的常量值。

4. 方法区域,用来列举该类中的各个方法。

除了方法描述符以及访问权限之外,每个方法还包括最为重要的代码区域(Code:)。

代码区域一开始会声明该方法中的操作数栈(stack=2)和局部变量数目(locals=3)的最大值,以及该方法接收参数的个数(args_size=1)。注意这里局部变量指的是字节码中的局部变量,而非 Java 程序中的局部变量。

接下来则是该方法的字节码。每条字节码均标注了对应的偏移量(bytecode index,BCI),这是用来定位字节码的。比如说偏移量为 10 的跳转字节码 10: goto 35,将跳转至偏移量为 35 的字节码 35: aload_0。

紧跟着的异常表(Exception table:)也会使用偏移量来定位每个异常处理器所监控的范围(由 from 到 to 的代码区域),以及异常处理器的起始位置(target)。除此之外,它还会声明所捕获的异常类型(type)。其中,any 指代任意异常类型。

再接下来的行数表(LineNumberTable:)则是 Java 源程序到字节码偏移量的映射。如果你在编译时使用了 -g 参数(javac -g Foo.java),那么这里还将出现局部变量表(LocalVariableTable:),展示 Java 程序中每个局部变量的名字、类型以及作用域。

行数表和局部变量表均属于调试信息。Java 虚拟机并不要求 class 文件必备这些信息。

最后则是字节码操作数栈的映射表(StackMapTable: number_of_entries = 3)。该表描述的是字节码跳转后操作数栈的分布情况,一般被 Java 虚拟机用于验证所加载的类,以及即时编译相关的一些操作,正常情况下,你无须深入了解。



推荐阅读
  • 【技术分享】一个 ELF 蠕虫分析
    【技术分享】一个 ELF 蠕虫分析 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 初识java关于JDK、JRE、JVM 了解一下 ... [详细]
  • 生产环境下JVM调优参数的设置实例
     正文前先来一波福利推荐: 福利一:百万年薪架构师视频,该视频可以学到很多东西,是本人花钱买的VIP课程,学习消化了一年,为了支持一下女朋友公众号也方便大家学习,共享给大家。福利二 ... [详细]
  • yahoo对付伪造跨站请求的办法是在表单里加入一个叫.crumb的随机串;而facebook也有类似的解决办法,它的表单里常常会有post_form_i ... [详细]
  • 加密、解密、揭秘
    谈PHP中信息加密技术同样是一道面试答错的问题,面试官问我非对称加密算法中有哪些经典的算法?当时我愣了一下,因为我把非对称加密与单项散列加 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
author-avatar
mobiledu2502907897
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有