@使用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 ...
随机推荐
- android Webview Html5 相关文章
Android WebView的使用集锦(支持Html5) http://blog.csdn.net/l_215851356/article/details/69239643 WebView详解与简单 ...
- [BZOJ4942][Noi2017]整数 线段树+压位
用线段树来模拟加减法过程,维护连续一段中是否全为0/1. 因为数字很大,我们60位压一位来处理. #include<iostream> #include<cstring> #i ...
- AC日记——[USACO5.4]奶牛的电信Telecowmunication 洛谷 P1345
[USACO5.4]奶牛的电信Telecowmunication 思路: 水题: 代码: #include <cstdio> #include <cstring> #inclu ...
- python元类:type和metaclass
python元类:type和metaclass python中一切皆对象,所以类本身也是对象.类有创建对象的能力,那谁来创建类的呢?答案是type. 1.用tpye函数创建一个类 class A(ob ...
- JAVA编程思想读书笔记(二)--容器
接上篇JAVA编程思想读书笔记(一) 第八章.对象的容纳 No1: java提供了四种类型的集合类:Vector(矢量).BitSet(位集).Stack(堆栈).Hashtable(散列表) No2 ...
- luogu P2107 小Z的AK计划
最近复习了一下堆,于是去luogu上找一些简单题写一写 贪心的想,小z不会到一半以后回头去Ak,因为这样从时间上想肯定是不优的,他可以早在之间经过时就AK所以我们可以将所有机房按照横坐标排序可以想到的 ...
- MySQL笔记(三)之数据插入更新与删除
INSERT INTO INSERT INTO 语句用于向表格中插入新的行. 语法: INSERT INTO 表 VALUES (值1, 值2,....) # 列数必须和值的个数匹配 INSERT I ...
- 2018 计算之道初赛第二场 阿里巴巴的手机代理商(困难)(反向可持久化Trie)
阿里巴巴的手机代理商(困难) 阿里巴巴的手机代理商正在研究 infra 输入法的新功能.他们需要分析单词频率以改进用户输入法的体验.于是需要你在系统内核里面写一个 API. API 有如下功能: 添加 ...
- 【推导】【贪心】【高精度】Gym - 101194E - Bet
题意:每个队伍有个赔率pi,如果你往他身上押x元,它赢了,那么你得到x+(1/pi)x元,否则你一分都得不到.问你最多选几支队伍去押,使得存在一种押的方案,不论你押的那几支队伍谁赢,你都能赚得到钱. ...
- MySql默认编码所造成的乱码麻烦1.222
1.前言 MySQL在安装时,最后的一步,会让你选择MySQL服务器及客户端.数据库.连接接口的默认编码.通常可选择 UTF8和GB2312. 但是,如果你选择了utf8的时候,恰好你要从另一个数据库 ...