@使用javap反编译Java字节码文件
在Sun公司提供的JDK中,就已经内置了Java字节码文件反编译工具javap.exe(位于JDK安装目录的bin文件夹下)。
我们可以在dos窗口中使用javap来反汇编指定的Java字节码文件。在使用javap的相关dos命令之前,你必须确保已经将JDK安装目录\bin添加到环境变量path中。
接着,我们就可以使用javap来反编译指定的Java字节码文件了。在此之前,我们先通过javap的帮助命令javap -help查看javap相关指令的用法。
C:\Users\winner_0715>javap -help
用法: javap <options> <classes>
其中, 可能的选项包括:
-help --help -? 输出此用法消息
-version 版本信息
-v -verbose 输出附加信息
-l 输出行号和本地变量表
-public 仅显示公共类和成员
-protected 显示受保护的/公共类和成员
-package 显示程序包/受保护的/公共类
和成员 (默认)
-p -private 显示所有类和成员
-c 对代码进行反汇编
-s 输出内部类型签名
-sysinfo 显示正在处理的类的
系统信息 (路径, 大小, 日期, MD5 散列)
-constants 显示最终常量
-classpath <path> 指定查找用户类文件的位置
-cp <path> 指定查找用户类文件的位置
-bootclasspath <path> 覆盖引导类文件的位置
从上述内容我们可以知道,javap的使用命令格式为javap 选项参数 类名,其中选项参数可以有多个,中间用空格隔开,也可以一个都没有。下面我们编写如下源代码文件(包名test,类名Person),并将其编译为Person.class字节码文件。
package test;
public class Person {
public Person(String name, int age, boolean gender, String address) {
this.name = name;
this.age = age;
this.gender = gender;
this.address = address;
}
// private修饰符
private String name;
// 默认无访问修饰符(即下面所说的package、friendly)
int age;
// protected修饰符
protected boolean gender;
// public修饰符
public String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void sayHi() {
System.out.println("Hello, my name is " + this.name);
}
}
接着将包名文件夹test及Person.class放置在D:\java目录下。以便于我们使用javap命令进行测试。
在执行命令之前,我们需要将dos窗口的当前工作目录变更为D:\java\test。
1、使用不带任何选项参数的命令:javap Person
D:\java\test>javap Person
警告: 二进制文件Person包含test.Person
Compiled from "Person.java"
public class test.Person {
int age;
protected boolean gender;
public java.lang.String address;
public test.Person(java.lang.String, int, boolean, java.lang.String);
public java.lang.String getName();
public void setName(java.lang.String);
public void sayHi();
}
javap Person和javap -package Person的显示结果一样,因为-package选项参数是默认的,用于显示package(不带任何访问修饰符,即我们常说的friendly)、protected、public修饰的类或成员。不会显示私有成员的属性
备注:在dos下进入工作目录D:\java,然后使用命令javap test.Person也可以实现上述操作。下同。
2、使用命令:javap -public Person显示public修饰的类或成员。
D:\java\test>javap -public Person
警告: 二进制文件Person包含test.Person
Compiled from "Person.java"
public class test.Person {
public java.lang.String address;
public test.Person(java.lang.String, int, boolean, java.lang.String);
public java.lang.String getName();
public void setName(java.lang.String);
public void sayHi();
}
与此类似,选项参数-protected用于显示protected以上访问级别(protected、public)的类或成员;选项参数-private用于显示private以上访问级别,也就是所有的类或成员。
3、使用命令:javap -public -l Person显示public修饰的类或成员,并显示行号表格和本地变量表格。
D:\java\test>javap -public -l Person
警告: 二进制文件Person包含test.Person
Compiled from "Person.java"
public class test.Person {
public java.lang.String address; public test.Person(java.lang.String, int, boolean, java.lang.String);
LineNumberTable:
line 4: 0
line 5: 4
line 6: 9
line 7: 14
line 8: 19
line 9: 25
LocalVariableTable:
Start Length Slot Name Signature
0 26 0 this Ltest/Person;
0 26 1 name Ljava/lang/String;
0 26 2 age I
0 26 3 gender Z
0 26 4 address Ljava/lang/String; public java.lang.String getName();
LineNumberTable:
line 21: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Ltest/Person; public void setName(java.lang.String);
LineNumberTable:
line 25: 0
line 26: 5
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this Ltest/Person;
0 6 1 name Ljava/lang/String; public void sayHi();
LineNumberTable:
line 29: 0
line 30: 28
LocalVariableTable:
Start Length Slot Name Signature
0 29 0 this Ltest/Person;
4、使用命令:javap -c Person显示Person.class反汇编出的字节码命令。
D:\java\test>javap -c Person
警告: 二进制文件Person包含test.Person
Compiled from "Person.java"
public class test.Person {
int age; protected boolean gender; public java.lang.String address; public test.Person(java.lang.String, int, boolean, java.lang.String);
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: aload_1
6: putfield #2 // Field name:Ljava/lang/String;
9: aload_0
10: iload_2
11: putfield #3 // Field age:I
14: aload_0
15: iload_3
16: putfield #4 // Field gender:Z
19: aload_0
20: aload 4
22: putfield #5 // Field address:Ljava/lang/String;
25: return public java.lang.String getName();
Code:
0: aload_0
1: getfield #2 // Field name:Ljava/lang/String;
4: areturn public void setName(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #2 // Field name:Ljava/lang/String;
5: return public void sayHi();
Code:
0: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
3: new #7 // class java/lang/StringBuilder
6: dup
7: invokespecial #8 // Method java/lang/StringBuilder."<init>":()V
10: ldc #9 // String Hello, my name is
12: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: aload_0
16: getfield #2 // Field name:Ljava/lang/String;
19: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: invokevirtual #11 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
25: invokevirtual #12 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
28: return
}
由于选项参数之间组合较多,因此其他选项参数不再一一截图赘述,仅在下面使用文字进行说明:
- -classpath <pathlist>
- 手动指定用户class字节码文件的存放目录,javap程序将在此目录下查找class文件,多个路径以英文分号分隔。例如:javap -classpath D:\java\test Person(即使DOS窗口的当前工作目录为其他任意路径,该命令均可正确执行)。
- -s
- 打印变量的内部类型签名,例如:javap -classpath D:\java\test -s Person。
- -extdirs <dirs>
- 指定javap搜索已安装的java扩展的位置,默认的java扩展的位置为jre\lib\ext。例如:javap -classpath D:\java\test -extdirs D:\java\myext Person
- -bootclasspath <pathlist>
- 指定使用Java底层类加载器(bootstrap class loader)加载的字节码文件的位置。例如:javap -classpath D:\java\test -bootclasspath D:\java\core Person
- -verbose
- 打印方法参数和本地变量的数量以及栈区大小。
- -J<flag>
- 使用javap.exe来执行java.exe虚拟机的相关命令,例如javap -J-version相当于java -version,可以有多个命令,中间以空格隔开。
@使用javap反编译Java字节码文件的更多相关文章
- 使用uncompyle2直接反编译python字节码文件pyo/pyc
update:在Mac OS X版的September 10, 2014版(5.0.9-1)中发现安装目录中的src.zip已更换位置至WingIDE.app/Contents/Resources/b ...
- Android反编译(一)之反编译JAVA源码
Android反编译(一) 之反编译JAVA源码 [目录] 1.工具 2.反编译步骤 3.实例 4.装X技巧 1.工具 1).dex反编译JAR工具 dex2jar http://code.go ...
- OpenJDK源码研究笔记(八)-详细解析如何读取Java字节码文件(.class)
在上一篇OpenJDK源码研究笔记(七)–Java字节码文件(.class)的结构中,我们大致了解了Java字节码文件的结构. 本篇详细地介绍了如何读取.class文件的大部分细节. 1.构造文件 ...
- OpenJDK源码研究笔记(七)–Java字节码文件(.class)的结构
最近在看OpenJDK源码的过程中,顺便看了Java编译器(javac)的源码. 为了理解javac的源码,需要先搞懂Java字节码文件(.class)的结构. 于是,我就认真看了下OpenJDK中J ...
- 【synchronized锁】通过synchronized锁 反编译查看字节码指令分析synchronized关键字修饰方法与代码块的区别
前提: 首先要铺垫几个前置的知识: Java中的锁如sychronize锁是对象锁,Java对象头中具有标识位,当对象锁升级为重量级锁时,重量级锁的标识位会指向监视器monitor, 而每个Java对 ...
- java字节码文件 helloworld
Java代码 \\A.java public class A{} 1 2 1 2 javac A.java \\得到 A.class javap -v A.class 下面是javap工具帮我们生成的 ...
- python反编译之字节码
如果你曾经写过或者用过 Python,你可能已经习惯了看到 Python 源代码文件:它们的名称以.Py 结尾.你可能还见过另一种类型的文件是 .pyc 结尾的,它们就是 Python "字 ...
- java字节码文件
查看字节码文件: javap -verbose HellloWorld.class
- 查看 java 中的编译的字节码文件
javap -c Atomicity ---------- javap -c 产生的字节码文件---------- Compiled from "Atomicity.java" p ...
随机推荐
- day4 递归二分法查找
现有一个序列,data=[for i in range(1,5000,3)],现在要求看一个数是否在列表中存在,我们知道,我们可以使用in或__contains__()的方法,判断一个值是否在列表中, ...
- 【LOJ】 #2009. 「SCOI2015」小凸玩密室
题解 神仙dp啊QAQ 我们发现我们需要枚举一个起点,遍历完它所有的儿子然后向上爬 设\(f[i][j]\)表示第i个点的子树全部处理完之后到达i深度为j的祖先的兄弟处 我们只需要对叶子节点和只有一个 ...
- 定期删除30天以前的elasticsearch的日志
脚本/scripts/delete-elk.log #!/bin/bash DATE=`date -d "1 days ago" +%Y.%m.%d` ip=`ifconfig e ...
- C++的一道变态题
题目大概是这样的:有两个数组a[N],b[N],求构造 b[i]=a[0]*a[1]*a[2]*...a[N-1]/a[i], 要求: .不能使用除法. .空间复杂度O(1),时间复杂度O(n). . ...
- [C#] 实现可设置超时的 Task
前言 如何实现支持超时的 Task ? 关键点: Task.WhenAny 实现 一个扩展方法就可以搞定. // 有返回值 public static async Task<TResult> ...
- springMVC整合freemarker遇到的问题 maven
java.lang.IllegalAccessError: tried to access method freemarker.ext.servlet.AllHttpScopesHashModel.& ...
- bWAPP练习--injection篇之HTML Injection - Reflected (POST)
POST的和之前的GET的过程差不多,只是表单的提交方式不一样而已. low 我们在表单中填入一个超链接 <a href="http://www.cnblogs.com/ESHLkan ...
- 腾讯后台研发暑期实习offer经历
昨晚看到腾讯校招的微信状态,一颗心终于落下来了,终于可以去梦寐以求的鹅厂工作了.想想这一个多月以来,心情就像过山车一样,此起彼伏,一会充满希望,一会又跌入谷底. 三月份的时候,听说腾讯可以内推了,我内 ...
- 我的OI生涯 第四章
第四章 晚上来机房的人越来越多了,我也注意到一个常年独自坐在一个角落的男人————郝哥. 郝哥为人很安静,只是那时我还不知道他好不好,就没有与他交流过什么,这个优秀的男人以后我们还会提到,这里先不讲. ...
- SHELL异常处理(转载)
写SHELL好久了,经常被异常困扰,可竟然坚持了若干年没用过,回想以前服务过的公司,阿弥陀佛,罪过罪过.废话少说,希望此篇文章可以协助大家和我彻底结束SHELL脚本就是LINUX命令集合的初级阶段. ...