使用javassist修改class文件

合集下载

Javassist用法详解

Javassist用法详解

Javassist⽤法详解⽬录概述ClassPoolCtClassCtMthodCtFieldCtConstructorClassPathClassLoader⽰例创建Class⽂件调⽤⽣成的类对象修改现有的类对象概述Java字节码以⼆进制的形式存储在.class⽂件中,每⼀个.class⽂件包含⼀个Java类或接⼝。

Javaassist就是⼀个⽤来处理Java字节码的类库。

它可以在⼀个已经编译好的类中添加新的⽅法,或者是修改已有的⽅法,并且不需要对字节码⽅⾯有深⼊的了解。

同时也可以通过完全⼿动的⽅式⽣成⼀个新的类对象。

Maven依赖⽅式:<dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.27.0-GA</version></dependency>Gradle依赖⽅式:implementation 'org.javassist:javassist:3.27.0-GA'ClassPoolClassPool是CtClass对象的容器,它按需读取类⽂件来构造CtClass对象,并且保存CtClass对象以便以后使⽤。

从实现的⾓度来看,ClassPool 是⼀个存储 CtClass 的 Hash 表,类的名称作为 Hash 表的 key。

ClassPool 的 get() 函数⽤于从 Hash 表中查找 key 对应的 CtClass 对象。

如果没有找到,get() 函数会创建并返回⼀个新的 CtClass 对象,这个新对象会保存在 Hash 表中。

需要注意的是ClassPool会在内存中维护所有被它创建过的CtClass,当CtClass数量过多时,会占⽤⼤量的内存,API中给出的解决⽅案是重新创建ClassPool 或有意识的调⽤CtClass的detach()⽅法以释放内存。

javaassist替换类路径

javaassist替换类路径

javaassist替换类路径使用Javaassist替换类路径Java是一种广泛使用的编程语言,它具有强大的功能和灵活的特性。

在Java开发过程中,有时我们需要对类进行动态修改或增强。

这时,Javaassist(Java Programming Assistant)就是一个非常有用的工具。

Javaassist是一个开源的Java字节码编辑器库,它提供了一组API,可以在运行时修改或生成Java字节码。

通过使用Javaassist,我们可以实现在运行时动态修改类的行为,而无需修改源代码。

Javaassist的一个常见应用场景是替换类路径。

类路径是指在Java 虚拟机(JVM)上运行Java程序时,用于查找类文件的路径。

在某些情况下,我们可能需要将程序中某个类的类路径替换为另一个类路径,以实现一些特定的需求。

而Javaassist提供了相应的API,可以帮助我们实现这一目标。

下面我们将介绍如何使用Javaassist替换类路径。

我们需要在项目中引入Javaassist的库文件。

可以通过在项目的构建文件(如Maven的pom.xml)中添加相应的依赖项来实现。

引入Javaassist后,我们就可以在代码中使用Javaassist提供的API 了。

下面是替换类路径的示例代码:```import javassist.ClassPool;import javassist.CtClass;import javassist.LoaderClassPath;public class ClassPathReplacer {public static void replaceClassPath(String className, String newClassPath) throws Exception {ClassPool classPool = ClassPool.getDefault();classPool.insertClassPath(newLoaderClassPath(ClassLoader.getSystemClassLoader()));CtClass ctClass = classPool.get(className);ctClass.defrost();ctClass.replaceClassName(className, newClassPath);ctClass.writeFile();}}```在上面的示例代码中,我们首先创建了一个ClassPool对象,它是Javaassist的核心类之一。

借助jclasslib与javassist修改java+class字节码

借助jclasslib与javassist修改java+class字节码

有时候,我们在没有java源程序的情况下,想改变.CLASS文件的部分内容输出或者改变跳转流,怎么办呢?介绍2个java hacker的工具javassist 以及jclasslib。

下载javassist-3.1RC2和jclasslib_windows_3_0。

解压后,将2个JAR 加入classpath内。

jclasslib_windows_3_0.exe在JAVA_HOME/lib下安装原文件HelloWorld.javapackage com.unmi;public class HelloWorld{public static void main(String[] args){System.out.println("Hello,gorld!");}}想修改输出的”hello world”,用jclasslib.exe 检测可以看到属于常量池的23。

如下代码就针对23 做调整。

package com.unmi;import javassist.ClassPool;import javassist.CtClass;import javassist.CtMethod;import java.io.*;import org.gjt.jclasslib.io.ClassFileWriter;import org.gjt.jclasslib.structures.CPInfo;import org.gjt.jclasslib.structures.ClassFile;import org.gjt.jclasslib.structures.constants.ConstantStringInfo;import org.gjt.jclasslib.structures.constants.ConstantUtf8Info;public class JclasslibTest {public static void main(String[] args) throws Exception {{String filePath = "D:\\java_proj\\com\\unmi\\HelloWorld.class";FileInputStream fis = new FileInputStream(filePath);DataInput di = new DataInputStream(fis);ClassFile cf = new ClassFile();cf.read(di);CPInfo[] infos = cf.getConstantPool();int count = infos.length;for (int i = 0; i < count; i++) {if (infos[i] != null) {System.out.print(i);System.out.print(" = ");System.out.print(infos[i].getVerbose());System.out.print(" = ");System.out.println(infos[i].getTagVerbose());if(i == 23){ConstantUtf8Info uInfo = (ConstantUtf8Info)infos[i];uInfo.setString("china alibaba ");}}}cf.setConstantPool(infos);fis.close();File f = new File(filePath + "c");ClassFileWriter.writeToFile(f, cf);}}}D:\java_proj>javac -cp %CLASSPATH%;. com/unmi/JclasslibTest.javaD:\java_proj>java com.unmi.JclasslibTest1 = com/unmi/HelloWorld = CONSTANT_Class_info2 = com/unmi/HelloWorld = CONSTANT_Utf8_info3 = java/lang/Object = CONSTANT_Class_info4 = java/lang/Object = CONSTANT_Utf8_info5 = <init> = CONSTANT_Utf8_info6 = ()V = CONSTANT_Utf8_info7 = Code = CONSTANT_Utf8_info8 = java/lang/Object.<init> = CONSTANT_Methodref_info9 = <init>()V = CONSTANT_NameAndType_info10 = LineNumberTable = CONSTANT_Utf8_info11 = LocalVariableTable = CONSTANT_Utf8_info12 = this = CONSTANT_Utf8_info13 = Lcom/unmi/HelloWorld; = CONSTANT_Utf8_info14 = main = CONSTANT_Utf8_info15 = ([Ljava/lang/String;)V = CONSTANT_Utf8_info16 = java/lang/System.out = CONSTANT_Fieldref_info17 = java/lang/System = CONSTANT_Class_info18 = java/lang/System = CONSTANT_Utf8_info19 = outLjava/io/PrintStream; = CONSTANT_NameAndType_info20 = out = CONSTANT_Utf8_info21 = Ljava/io/PrintStream; = CONSTANT_Utf8_info22 = Hello,gorld! = CONSTANT_String_info23 = Hello,gorld! = CONSTANT_Utf8_info24 = java/io/PrintStream.println = CONSTANT_Methodref_info25 = java/io/PrintStream = CONSTANT_Class_info26 = java/io/PrintStream = CONSTANT_Utf8_info27 = println(Ljava/lang/String;)V = CONSTANT_NameAndType_info28 = println = CONSTANT_Utf8_info29 = (Ljava/lang/String;)V = CONSTANT_Utf8_info30 = args = CONSTANT_Utf8_info31 = [Ljava/lang/String; = CONSTANT_Utf8_info32 = SourceFile = CONSTANT_Utf8_info33 = HelloWorld.java = CONSTANT_Utf8_info更改生成的HelloWorld.classc 为HelloWorld.class执行输出为D:\java_proj>java com.unmi.HelloWorldchina alibaba 另外,也可以修改if 语句跳转Jclasslib 观测到jvm op code 如下现在想更改>= 为<,怎么办?查询Opcode Mnemonics by Opcode/docs/books/jvms/second_edition/html/Mnemonics.doc.html 并查到>= 的操作码为0xA1所以只要用Ultraedit 修改0xA1 为0xA2 就可以了。

javassist使用流程

javassist使用流程

javassist使用流程javassist是一个开源的Java字节码编辑器库,它提供了一种在运行时修改类文件的方式,可以动态地创建、编辑和修改Java类。

使用javassist可以实现一些在编译时无法完成的操作,比如动态生成类、修改类的行为等。

下面将介绍javassist的使用流程。

1. 引入javassist库首先需要在项目中引入javassist库。

可以通过Maven或手动下载jar包的方式引入。

在引入后,就可以在代码中使用javassist的功能了。

2. 创建ClassPoolClassPool是javassist的核心类,它用于管理被修改的类。

通过ClassPool可以获取要修改的类的CtClass对象,以及创建新的类。

可以通过以下代码创建ClassPool对象:```ClassPool classPool = ClassPool.getDefault();```3. 获取要修改的类通过ClassPool的get方法可以获取要修改的类的CtClass对象。

get方法的参数可以是类的全限定名,也可以是Class对象。

例如,获取ng.String类的CtClass对象可以使用以下代码:```CtClass stringClass = classPool.get("ng.String");```4. 修改类的行为获取到要修改的类的CtClass对象后,就可以对类的行为进行修改了。

可以使用CtClass提供的一系列方法来添加、修改或删除类的成员、方法和字段。

以下是一些常用的示例操作:- 添加方法:```CtMethod newMethod = CtNewMethod.make("public void newMethod() { System.out.println(\"This is a new method.\"); }", ctClass);ctClass.addMethod(newMethod);```- 修改方法:```CtMethod method = ctClass.getDeclaredMethod("methodName");method.insertBefore("{ System.out.println(\"This is insertedbefore the method.\"); }");```- 删除方法:```CtMethod method = ctClass.getDeclaredMethod("methodName");ctClass.removeMethod(method);```- 添加字段:```CtField newField = new CtField(CtClass.intType, "newField", ctClass);ctClass.addField(newField);```- 修改字段:```CtField field = ctClass.getDeclaredField("fieldName");field.setModifiers(Modifier.PRIVATE);```- 删除字段:```CtField field = ctClass.getDeclaredField("fieldName"); ctClass.removeField(field);```5. 生成修改后的类在对类进行修改后,需要将修改后的类写回到磁盘上,或者在内存中动态加载。

javassist使用全解析

javassist使用全解析

javassist使⽤全解析Java 字节码以⼆进制的形式存储在 .class ⽂件中,每⼀个 .class ⽂件包含⼀个 Java 类或接⼝。

Javaassist 就是⼀个⽤来处理 Java 字节码的类库。

它可以在⼀个已经编译好的类中添加新的⽅法,或者是修改已有的⽅法,并且不需要对字节码⽅⾯有深⼊的了解。

同时也可以去⽣成⼀个新的类对象,通过完全⼿动的⽅式。

1. 使⽤ Javassist 创建⼀个 class ⽂件⾸先需要引⼊jar包:<dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.25.0-GA</version></dependency>编写创建对象的类:package com.rickiyang.learn.javassist;import javassist.*;/*** @author rickiyang* @date 2019-08-06* @Desc*/public class CreatePerson {/*** 创建⼀个Person 对象** @throws Exception*/public static void createPseson() throws Exception {ClassPool pool = ClassPool.getDefault();// 1. 创建⼀个空类CtClass cc = pool.makeClass("com.rickiyang.learn.javassist.Person");// 2. 新增⼀个字段 private String name;// 字段名为nameCtField param = new CtField(pool.get("ng.String"), "name", cc);// 访问级别是 privateparam.setModifiers(Modifier.PRIVATE);// 初始值是 "xiaoming"cc.addField(param, CtField.Initializer.constant("xiaoming"));// 3. ⽣成 getter、setter ⽅法cc.addMethod(CtNewMethod.setter("setName", param));cc.addMethod(CtNewMethod.getter("getName", param));// 4. 添加⽆参的构造函数CtConstructor cons = new CtConstructor(new CtClass[]{}, cc);cons.setBody("{name = \"xiaohong\";}");cc.addConstructor(cons);// 5. 添加有参的构造函数cons = new CtConstructor(new CtClass[]{pool.get("ng.String")}, cc);// $0=this / $1,$2,$3... 代表⽅法参数cons.setBody("{$ = $1;}");cc.addConstructor(cons);// 6. 创建⼀个名为printName⽅法,⽆参数,⽆返回值,输出name值CtMethod ctMethod = new CtMethod(CtClass.voidType, "printName", new CtClass[]{}, cc);ctMethod.setModifiers(Modifier.PUBLIC);ctMethod.setBody("{System.out.println(name);}");cc.addMethod(ctMethod);//这⾥会将这个创建的类对象编译为.class⽂件cc.writeFile("/Users/yangyue/workspace/springboot-learn/java-agent/src/main/java/");}public static void main(String[] args) {try {createPseson();} catch (Exception e) {e.printStackTrace();}}}执⾏上⾯的 main 函数之后,会在指定的⽬录内⽣成 Person.class ⽂件://// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)//package com.rickiyang.learn.javassist;public class Person {private String name = "xiaoming";public void setName(String var1) { = var1;}public String getName() {return ;}public Person() { = "xiaohong";}public Person(String var1) { = var1;}public void printName() {System.out.println();}}跟咱们预想的⼀样。

java修改class文件

java修改class文件

java修改class⽂件最近因为⼯作需要修改class⽂件中⼀个变量的值,特此记录2、找到要修改的变量所在的地址3、创建⼀个java⼯程、并且将jclasslib.jar导⼊、执⾏以下代码即可1package .c;23import java.io.*;4import org.gjt.jclasslib.io.ClassFileWriter;5import org.gjt.jclasslib.structures.CPInfo;6import org.gjt.jclasslib.structures.ClassFile;7import org.gjt.jclasslib.structures.constants.ConstantUtf8Info;89public class Main {10public static void main(String[] args) throws Exception {1112 String filePath = "C:\\Main.class";13 FileInputStream fis = new FileInputStream(filePath);14 DataInput di = new DataInputStream(fis);15 ClassFile cf = new ClassFile();16 cf.read(di);17 CPInfo[] infos = cf.getConstantPool();1819int count = infos.length;20for (int i = 0; i < count; i++) {21if (infos[i] != null) {22 System.out.print(i);23 System.out.print(" = ");24 System.out.print(infos[i].getVerbose());25 System.out.print(" = ");26 System.out.println(infos[i].getTagVerbose());27if (i == 21) {//刚刚找到的是21位置28 ConstantUtf8Info uInfo = (ConstantUtf8Info) infos[i]; //刚刚那⾥是CONSTANT_Utf-8_info所以这⾥要⽤这个29 uInfo.setBytes("baidu".getBytes());30 infos[i] = uInfo;31 }32 }33 }34//这种⽅式也可以,⼀样的35/* if(infos[count] != null) {36 ConstantUtf8Info uInfo = (ConstantUtf8Info) infos[i]; //刚刚那⾥是CONSTANT_Utf-8_info所以这⾥要⽤这个37 uInfo.setBytes("baidu".getBytes());38 infos[count] = uInfo;39 }*/4041 cf.setConstantPool(infos);42 fis.close();43 File f = new File(filePath);44 ClassFileWriter.writeToFile(f, cf);45 }46 }。

javassist jar 修改 方法

javassist jar 修改 方法

javassist jar 修改方法摘要:1.简介2.javassist 是什么3.如何使用javassist 修改jar 包4.修改方法5.总结正文:1.简介在Java 开发中,我们有时需要对jar 包进行一些修改,例如添加、删除或修改类、方法等。

javassist 是一个Java 字节码修改框架,它可以帮助我们轻松地实现这些操作。

2.javassist 是什么Javassist 是一个强大的Java 字节码修改工具,它可以让Java 程序在运行时动态地修改类和字节码。

它支持对类、方法、字段等进行操作,提供了丰富的API 供开发者使用。

3.如何使用javassist 修改jar 包要使用javassist 修改jar 包,首先需要将jar 包转换为Class 文件,然后使用Javassist 的API 对Class 文件进行修改。

接下来,将修改后的Class 文件重新打包成jar 包。

具体步骤如下:a.将jar 包转换为Class 文件使用`jar2class`工具将jar 包转换为Class 文件,例如:`jar2class -x input.jar output`。

b.使用Javassist 修改Class 文件使用Javassist 的API 对Class 文件进行修改,例如:```javaClassPool pool = new ClassPool();pool.appendClassPath(new File("input.jar"));CtClass ctClass = pool.getCtClass("com.example.ClassName");// 修改方法CtMethod method = ctClass.getDeclaredMethod("methodName");method.setBody("{System.out.println("修改后的方法实现");}");// 添加方法CtMethod newMethod = CtMethod.make(Modifier.PUBLIC, ctClass, "newMethodName", new CtClass[]{}, "{}");ctClass.addMethod(newMethod);// 删除字段ctClass.removeField("fieldName");// 修改字段ctClass.getField("fieldName").setModifiers(Modifier.PRIVATE);// 保存修改后的Class 文件ctClass.writeFile("output.class");```c.将修改后的Class 文件重新打包成jar 包使用`jar`命令将修改后的Class 文件打包成jar 包,例如:`jar cvf output.jar output.class`。

javassist jar 修改 方法

javassist jar 修改 方法

javassist jar 修改方法【实用版3篇】目录(篇1)1.Javassist 简介2.Javassist 的功能3.如何使用 Javassist 修改 jar 文件中的方法4.注意事项和局限性正文(篇1)一、Javassist 简介Javassist(Java Class File Processor)是一个开源的 Java 字节码处理工具,它可以对 Java 字节码进行编辑、修改、生成等操作。

使用Javassist,我们可以在保持 Java 代码不变的情况下,修改其行为。

这对于一些需要对已有代码进行定制,但又不想修改原有代码的情况非常有用。

二、Javassist 的功能Javassist 的主要功能有:1.读取和修改 Java 类文件的字节码。

2.生成新的 Java 类文件。

3.动态地创建和修改 Java 类的行为。

4.为 Java 类添加、删除或修改方法、字段等。

三、如何使用 Javassist 修改 jar 文件中的方法下面是一个使用 Javassist 修改 jar 文件中的方法的简单示例:1.首先,需要导入 Javassist 相关的库。

```javaimport javassist.ClassPool;import javassist.CtClass;import javassist.CtMethod;import javassist.Modifier;import java.io.File;import java.io.FileInputStream;import java.io.IOException;```2.然后,创建一个 ClassPool 实例,用于加载和修改类文件。

```javaClassPool pool = new ClassPool();```3.指定要修改的 jar 文件路径,并加载到 ClassPool 中。

```javaFile jarFile = new File("path/to/your/jarfile.jar"); FileInputStream fis = new FileInputStream(jarFile); pool.open(fis, "jar");```4.通过 ClassPool 实例,获取需要修改的方法所在的类。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

本文由beikexiami贡献 doc1。

使用 javassist 修改 class 文件 Firestorm 是一个用 JAVA 写的代码生成工具,可以替你节省很多的代码量,可以说同类软件中功能最强 的一个。

 Firestorm 是一个用 JAVA 写的代码生成工具,可以替你节省很多的代码量,可以说同类软件中功能最强 的一个。

 你可以在网上下载到最新的 2.3 试用版本,同时网站会发给你一个试用的 license 文件。

既然是试用, 那么在使用上肯定有一定的限制。

主要限制有 3 个: 1.只能最多生成 5 张表的 DAO; 2.有时间限制; 3.不能自己定制代码生成; 为了能够更好的试用这个软件,我得改改它,去掉这些限制。

将 firestorm.jar 打开后,可以看到它使用 了 混淆器进行代码保护, 不同于大多数的混淆器生成的文件, 它的 class 和 package 大部分都是以关键字来 命名, 所以如果你用 JAD 之类的工具把它反编译后是不能再把它编译成功,编译器会提示出错误。

 反编译后,找到几个有关注册的关键文件,发现它使用的是数字签名技术来做的保护,所以想逆向找出 注册码的计算方法是不可行的了,只能通过修改文件的方法来破解。

通常我们是先反编译,然后再修改 反编译后生成的原文件,最后再重新编译。

但是由于文件名和包名的关系我们无法进行编译,除非把它的 这些‘非法'的文件名和包名全部改成符合 java 语言规范的名称,由于类,包众多,互相调用也很 频繁,所以这种方法几乎不可能的。

 另外一种方法就是使用 softice 之类的调试软件来破解,不过这个脱离 JAVA 的范畴,这里不做讨论。

 还有一种方法可能很少有人用,就是先反编译得到原文件,然后找到关键的方法后修改它的字节码, 也就是 class 文件,这中方法往往需要你知道一些有关 CLASS 文件格式方面的知识(如果没有也不用担 心), 有许多的处理字节码的工具可以帮助你,比较流行的这类工具主要有:apache.org 的 BCEL; jboss.com 的 javassist;objectweb.org 的 asm。

都是出身名门哈。

这 3 个工具各有特点, 这次我选用 javassist,因为它修改 class 文件最方便,甚至不需要懂得字节码和 class 文件格式。

 让我们来看看具体步骤: step1: 下载并安装 FIRESTORM。

 step2: 反编译 jar 文件,阅读代码,找到关键的方法。

当然,我这里写出来,你就不用再麻烦了。

(其实这步 是最 麻烦的)。

 找到 com.codefutures.if.if 文件中的方法 public static boolean a(java.security.PublicKey publickey, byte abyte0[], byte abyte1[]) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException, java.security.InvalidKeyException, java.security.SignatureException { java.security.Signature java.security.Signature.getInstance("SHA1withDSA", "SUN"); signature.initVerify(publickey); signature.update(abyte0); return signature.verify(abyte1); } 这个方法是对公钥进行检验,修改的思路就是直接让他返回一个 true. signature = step2: 收到 firestorm.license 文件后不要急着安装,先修改如下: <custom-codegen>no</custom-codegen> 改为 <custom-codegen>yes</custom-codegen> <restriction>5</restriction> 改为 <restriction>none</restriction> <expiry-date>[日期]</expiry-date> 改为 <expiry-date>never</expiry-date> 修改后放到 firestorm 的安装路径的 license 目录。

step3: 修改 com.codefutures.if.if 的 class 文件.这里我们需要写一个小程序来完成实现: import javassist.ClassPool; import javassist.CtClass; import javassist.CtMethod; public class Test { public static void main(String[] args) throws Exception { ClassPool pool = ClassPool.getDefault(); //设置目标类的路径,确保能够找到需要修改的类,这里我指向 firestorm.jar //解包后的路径 pool.insertClassPath("d:/work/firestorm/firestorm") ; //获得要修改的类 CtClass cc = pool.get("com.codefutures.if.if"); //设置方法需要的参数 CtClass[] param = new CtClass[3] ; param[0] = pool.get("java.security.PublicKey") ; param[1] = pool.get("byte[]") ; param[2] = pool.get("byte[]") ; //得到方法 CtMethod m = cc.getDeclaredMethod("a", param); //插入新的代码 m.insertBefore("{return true ;}") ; //保存到文件里 cc.writeFile() ; } } 修改完后,你可以反编译修改过的的 class 文件,看看代码是否加入成功。

step4: 将所有的 class 文件重新打包成 firestorm.jar,然后替换 [firestorm 安装路径]/lib/firestorm.jar,再启动 firestorm 即可。

一、直接修改字节码 要查看“return false”对应字节码需要使用 JClassLib 工具,JClassLib 有一个可视 化的界面,方便我们查看类的变量、方法、静态数据等,如下图: 这个 a 方法(也许实际名称就是 sendsms)的字节码如下: 0 aload_0 1 invokestatic #42 <javax/microedition/io/Connector.open> 4 checkcast #11 <javax/wireless/messaging/MessageConnection> 7 dup 8 astore_2 9 ldc #61 <text> 11 invokeinterface #48 <javax/wireless/messaging/MessageConnection.newMessage> count 2 16 checkcast #12 <javax/wireless/messaging/TextMessage> 19 astore_3 20 aload_2 21 invokestatic #29 24 ifne 34 (+10) 27 aload_3 28 invokestatic #29 31 ifeq 36 (+5) 34 iconst_0 35 ireturn 36 aload_3 37 aload_0 38 invokeinterface #50 <javax/wireless/messaging/TextMessage.setAddress> count 2 43 aload_3 44 aload_1 45 invokeinterface #51 <javax/wireless/messaging/TextMessage.setPayloadText> count 2 50 aload_2 51 aload_3 52 invokeinterface #49 <javax/wireless/messaging/MessageConnection.send> count 2 57 aload_2 58 invokeinterface #47 <javax/wireless/messaging/MessageConnection.close> count 1 63 iconst_1 64 ireturn 65 pop 66 iconst_0 67 ireturn 通过查找 JVM 指令集, 0x03 iconst_0 int 型 1 推送至栈顶 ,0xac ireturn 的 将 int 型 0 推送至栈顶 , 0x04 iconst_1 将 从当前方法返回 int,很明显,63-67 行就是对应 return true; JVM INSTR pop ; return false; 这 5 行对应的 16 进制值是: 0x04,0xAC,0x57,0x03,0xAC,于是, 16 进制编辑器打开, 用 查找 04AC5703AC 的位置,果然不负众望,接下来你知道怎么做了吧,把 0x03 这个位置的值 换成 0x04,那么这个 return false 不就变成 return true 了,呵呵。

JVM 指令集及各指令的详细使用说明 1. 指令码 助记符 2. 0x00 nop 说明 什么都不做 将 int 型-1 推送至栈顶 将 int 型 0 推送至栈顶 将 int 型 1 推送至栈顶 将 int 型 2 推送至栈顶 将 int 型 3 推送至栈顶 将 int 型 4 推送至栈顶 将 int 型 5 推送至栈顶 将 long 型 0 推送至栈顶 将 long 型 1 推送至栈顶 将 float 型 0 推送至栈顶 将 float 型 1 推送至栈顶 将 float 型 2 推送至栈顶 将 double 型 0 推送至栈顶 将 double 型 1 推送至栈顶 将单字节的常量值(-128 ̄127)推送至栈顶 将一个短整型常量值(-32768 ̄32767)推送至栈顶 将 int, float 或 String 型常量值从常量池中推送至栈顶 将 int, float 或 String 型常量值从常量池中推送至栈顶(宽索引) 将 long 或 double 型常量值从常量池中推送至栈顶(宽索引) 将指定的 int 型本地变量推送至栈顶 将指定的 long 型本地变量推送至栈顶 将指定的 float 型本地变量推送至栈顶 将指定的 double 型本地变量推送至栈顶 将指定的引用类型本地变量推送至栈顶 将第一个 int 型本地变量推送至栈顶 将第二个 int 型本地变量推送至栈顶 将第三个 int 型本地变量推送至栈顶 3. 0x01 aconst_null 将 null 推送至栈顶 4. 0x02 iconst_m1 5. 0x03 iconst_0 6. 0x04 iconst_1 7. 0x05 iconst_2 8. 0x06 iconst_3 9. 0x07 iconst_4 10. 0x08 iconst_5 11. 0x09 lconst_0 12. 0x0a lconst_1 13. 0x0b fconst_0 14. 0x0c fconst_1 15. 0x0d fconst_2 16. 0x0e dconst_0 17. 0x0f dconst_1 18. 0x10 bipush 19. 0x11 sipush 20. 0x12 ldc 21. 0x13 ldc_w 22. 0x14 ldc2_w 23. 0x15 iload 24. 0x16 lload 25. 0x17 fload 26. 0x18 dload 27. 0x19 aload 28. 0x1a iload_0 29. 0x1b iload_1 30. 0x1c iload_2 31. 0x1d iload_3 32. 0x1e lload_0 33. 0x1f lload_1 34. 0x20 lload_2 35. 0x21 lload_3 36. 0x22 fload_0 37. 0x23 fload_1 38. 0x24 fload_2 39. 0x25 fload_3 40. 0x26 dload_0 41. 0x27 dload_1 42. 0x28 dload_2 43. 0x29 dload_3 44. 0x2a aload_0 45. 0x2b aload_1 46. 0x2c aload_2 47. 0x2d aload_3 48. 0x2e iaload 49. 0x2f laload 50. 0x30 faload 51. 0x31 daload 52. 0x32 aaload 53. 0x33 baload 54. 0x34 caload 55. 0x35 saload 56. 0x36 istore 57. 0x37 lstore 58. 0x38 fstore 59. 0x39 dstore 60. 0x3a astore 61. 0x3b istore_0 62. 0x3c istore_1 63. 0x3d istore_2 64. 0x3e istore_3 65. 0x3f lstore_0 66. 0x40 lstore_1 67. 0x41 lstore_2 68. 0x42 lstore_3 69. 0x43 fstore_0 70. 0x44 fstore_1 71. 0x45 fstore_2 72. 0x46 fstore_3 73. 0x47 dstore_0 74. 0x48 dstore_1 将第四个 int 型本地变量推送至栈顶 将第一个 long 型本地变量推送至栈顶 将第二个 long 型本地变量推送至栈顶 将第三个 long 型本地变量推送至栈顶 将第四个 long 型本地变量推送至栈顶 将第一个 float 型本地变量推送至栈顶 将第二个 float 型本地变量推送至栈顶 将第三个 float 型本地变量推送至栈顶 将第四个 float 型本地变量推送至栈顶 将第一个 double 型本地变量推送至栈顶 将第二个 double 型本地变量推送至栈顶 将第三个 double 型本地变量推送至栈顶 将第四个 double 型本地变量推送至栈顶 将第一个引用类型本地变量推送至栈顶 将第二个引用类型本地变量推送至栈顶 将第三个引用类型本地变量推送至栈顶 将第四个引用类型本地变量推送至栈顶 将 int 型数组指定索引的值推送至栈顶 将 long 型数组指定索引的值推送至栈顶 将 float 型数组指定索引的值推送至栈顶 将 double 型数组指定索引的值推送至栈顶 将引用型数组指定索引的值推送至栈顶 将 boolean 或 byte 型数组指定索引的值推送至栈顶 将 char 型数组指定索引的值推送至栈顶 将 short 型数组指定索引的值推送至栈顶 将栈顶 int 型数值存入指定本地变量 将栈顶 long 型数值存入指定本地变量 将栈顶 float 型数值存入指定本地变量 将栈顶 double 型数值存入指定本地变量 将栈顶引用型数值存入指定本地变量 将栈顶 int 型数值存入第一个本地变量 将栈顶 int 型数值存入第二个本地变量 将栈顶 int 型数值存入第三个本地变量 将栈顶 int 型数值存入第四个本地变量 将栈顶 long 型数值存入第一个本地变量 将栈顶 long 型数值存入第二个本地变量 将栈顶 long 型数值存入第三个本地变量 将栈顶 long 型数值存入第四个本地变量 将栈顶 float 型数值存入第一个本地变量 将栈顶 float 型数值存入第二个本地变量 将栈顶 float 型数值存入第三个本地变量 将栈顶 float 型数值存入第四个本地变量 将栈顶 double 型数值存入第一个本地变量 将栈顶 double 型数值存入第二个本地变量 75. 0x49 dstore_2 76. 0x4a dstore_3 77. 0x4b astore_0 78. 0x4c astore_1 79. 0x4d astore_2 80. 0x4e astore_3 81. 0x4f iastore 82. 0x50 lastore 83. 0x51 fastore 84. 0x52 dastore 85. 0x53 aastore 86. 0x54 bastore 87. 0x55 castore 88. 0x56 sastore 89. 0x57 pop 90. 0x58 pop2 91. 0x59 dup 92. 0x5a dup_x1 93. 0x5b dup_x2 94. 0x5c dup2 顶 95. 0x5d dup2_x1 96. 0x5e dup2_x2 97. 0x5f swap 98. 0x60 iadd 99. 0x61 ladd 100. 0x62 fadd 101. 0x63 dadd 102. 0x64 isub 103. 0x65 lsub 104. 0x66 fsub 105. 0x67 dsub 106. 0x68 imul 107. 0x69 lmul 108. 0x6a fmul 109. 0x6b dmul 110. 0x6c idiv 111. 0x6d ldiv 112. 0x6e fdiv 113. 0x6f ddiv 114. 0x70 irem 115. 0x71 lrem 116. 0x72 frem 117. 0x73 drem 将栈顶 double 型数值存入第三个本地变量 将栈顶 double 型数值存入第四个本地变量 将栈顶引用型数值存入第一个本地变量 将栈顶引用型数值存入第二个本地变量 将栈顶引用型数值存入第三个本地变量 将栈顶引用型数值存入第四个本地变量 将栈顶 int 型数值存入指定数组的指定索引位置 将栈顶 long 型数值存入指定数组的指定索引位置 将栈顶 float 型数值存入指定数组的指定索引位置 将栈顶 double 型数值存入指定数组的指定索引位置 将栈顶引用型数值存入指定数组的指定索引位置 将栈顶 boolean 或 byte 型数值存入指定数组的指定索引位置 将栈顶 char 型数值存入指定数组的指定索引位置 将栈顶 short 型数值存入指定数组的指定索引位置 将栈顶数值弹出 (数值不能是 long 或 double 类型的) 将栈顶的一个(long 或 double 类型的)或两个数值弹出(其它) 复制栈顶数值并将复制值压入栈顶 复制栈顶数值并将两个复制值压入栈顶 复制栈顶数值并将三个(或两个)复制值压入栈顶 复制栈顶一个(long 或 double 类型的)或两个(其它)数值并将复制值压入栈 <待补充> <待补充> 将栈最顶端的两个数值互换(数值不能是 long 或 double 类型的) 将栈顶两 int 型数值相加并将结果压入栈顶 将栈顶两 long 型数值相加并将结果压入栈顶 将栈顶两 float 型数值相加并将结果压入栈顶 将栈顶两 double 型数值相加并将结果压入栈顶 将栈顶两 int 型数值相减并将结果压入栈顶 将栈顶两 long 型数值相减并将结果压入栈顶 将栈顶两 float 型数值相减并将结果压入栈顶 将栈顶两 double 型数值相减并将结果压入栈顶 将栈顶两 int 型数值相乘并将结果压入栈顶 将栈顶两 long 型数值相乘并将结果压入栈顶 将栈顶两 float 型数值相乘并将结果压入栈顶 将栈顶两 double 型数值相乘并将结果压入栈顶 将栈顶两 int 型数值相除并将结果压入栈顶 将栈顶两 long 型数值相除并将结果压入栈顶 将栈顶两 float 型数值相除并将结果压入栈顶 将栈顶两 double 型数值相除并将结果压入栈顶 将栈顶两 int 型数值作取模运算并将结果压入栈顶 将栈顶两 long 型数值作取模运算并将结果压入栈顶 将栈顶两 float 型数值作取模运算并将结果压入栈顶 将栈顶两 double 型数值作取模运算并将结果压入栈顶 118. 0x74 ineg 119. 0x75 lneg 120. 0x76 fneg 121. 0x77 dneg 122. 0x78 ishl 123. 0x79 lshl 124. 0x7a ishr 125. 0x7b lshr 126. 0x7c iushr 127. 0x7d lushr 128. 0x7e iand 129. 0x7f land 130. 0x80 ior 131. 0x81 lor 132. 0x82 ixor 133. 0x83 lxor 134. 0x84 iinc 135. 0x85 i2l 136. 0x86 i2f 137. 0x87 i2d 138. 0x88 l2i 139. 0x89 l2f 140. 0x8a l2d 141. 0x8b f2i 142. 0x8c f2l 143. 0x8d f2d 144. 0x8e d2i 145. 0x8f d2l 146. 0x90 d2f 147. 0x91 i2b 148. 0x92 i2c 149. 0x93 i2s 150. 0x94 lcmp 151. 0x95 fcmpl 将栈顶 int 型数值取负并将结果压入栈顶 将栈顶 long 型数值取负并将结果压入栈顶 将栈顶 float 型数值取负并将结果压入栈顶 将栈顶 double 型数值取负并将结果压入栈顶 将 int 型数值左移位指定位数并将结果压入栈顶 将 long 型数值左移位指定位数并将结果压入栈顶 将 int 型数值右(符号)移位指定位数并将结果压入栈顶 将 long 型数值右(符号)移位指定位数并将结果压入栈顶 将 int 型数值右(无符号)移位指定位数并将结果压入栈顶 将 long 型数值右(无符号)移位指定位数并将结果压入栈顶 将栈顶两 int 型数值作“按位与”并将结果压入栈顶 将栈顶两 long 型数值作“按位与”并将结果压入栈顶 将栈顶两 int 型数值作“按位或”并将结果压入栈顶 将栈顶两 long 型数值作“按位或”并将结果压入栈顶 将栈顶两 int 型数值作“按位异或”并将结果压入栈顶 将栈顶两 long 型数值作“按位异或”并将结果压入栈顶 将指定 int 型变量增加指定值(i++, i--, i+=2) 将栈顶 int 型数值强制转换成 long 型数值并将结果压入栈顶 将栈顶 int 型数值强制转换成 float 型数值并将结果压入栈顶 将栈顶 int 型数值强制转换成 double 型数值并将结果压入栈顶 将栈顶 long 型数值强制转换成 int 型数值并将结果压入栈顶 将栈顶 long 型数值强制转换成 float 型数值并将结果压入栈顶 将栈顶 long 型数值强制转换成 double 型数值并将结果压入栈顶 将栈顶 float 型数值强制转换成 int 型数值并将结果压入栈顶 将栈顶 float 型数值强制转换成 long 型数值并将结果压入栈顶 将栈顶 float 型数值强制转换成 double 型数值并将结果压入栈顶 将栈顶 double 型数值强制转换成 int 型数值并将结果压入栈顶 将栈顶 double 型数值强制转换成 long 型数值并将结果压入栈顶 将栈顶 double 型数值强制转换成 float 型数值并将结果压入栈顶 将栈顶 int 型数值强制转换成 byte 型数值并将结果压入栈顶 将栈顶 int 型数值强制转换成 char 型数值并将结果压入栈顶 将栈顶 int 型数值强制转换成 short 型数值并将结果压入栈顶 比较栈顶两 long 型数值大小,并将结果(1,0,-1)压入栈顶 比较栈顶两 float 型数值大小,并将结果(1,0,-1)压入栈顶;当其中一 比较栈顶两 float 型数值大小,并将结果(1,0,-1)压入栈顶;当其中一 比较栈顶两 double 型数值大小,并将结果(1,0,-1)压入栈顶;当其中一 比较栈顶两 double 型数值大小,并将结果(1,0,-1)压入栈顶;当其中一 当栈顶 int 型数值等于 0 时跳转 当栈顶 int 型数值不等于 0 时跳转 当栈顶 int 型数值小于 0 时跳转 个数值为 NaN 时,将-1 压入栈顶 152. 0x96 fcmpg 个数值为 NaN 时,将 1 压入栈顶 153. 0x97 dcmpl 个数值为 NaN 时,将-1 压入栈顶 154. 0x98 dcmpg 个数值为 NaN 时,将 1 压入栈顶 155. 0x99 ifeq 156. 0x9a ifne 157. 0x9b iflt 158. 0x9c ifge 159. 0x9d ifgt 160. 0x9e ifle 当栈顶 int 型数值大于等于 0 时跳转 当栈顶 int 型数值大于 0 时跳转 当栈顶 int 型数值小于等于 0 时跳转 比较栈顶两 int 型数值大小,当结果等于 0 时跳转 比较栈顶两 int 型数值大小,当结果不等于 0 时跳转 比较栈顶两 int 型数值大小,当结果小于 0 时跳转 比较栈顶两 int 型数值大小,当结果大于等于 0 时跳转 比较栈顶两 int 型数值大小,当结果大于 0 时跳转 比较栈顶两 int 型数值大小,当结果小于等于 0 时跳转 比较栈顶两引用型数值,当结果相等时跳转 比较栈顶两引用型数值,当结果不相等时跳转 161. 0x9f if_icmpeq 162. 0xa0 if_icmpne 163. 0xa1 if_icmplt 164. 0xa2 if_icmpge 165. 0xa3 if_icmpgt 166. 0xa4 if_icmple 167. 0xa5 if_acmpeq 168. 0xa6 if_acmpne 169. 0xa7 goto 170. 0xa8 jsr 171. 0xa9 ret 无条件跳转 跳转至指定 16 位 offset 位置,并将 jsr 下一条指令地址压入栈顶 返回至本地变量指定的 index 的指令位置(一般与 jsr, jsr_w 联合使用) 用于 switch 条件跳转,case 值连续(可变长度指令) 用于 switch 条件跳转,case 值不连续(可变长度指令) 172. 0xaa tableswitch 173. 0xab lookupswitch 174. 0xac ireturn 175. 0xad lreturn 176. 0xae freturn 177. 0xaf dreturn 178. 0xb0 areturn 179. 0xb1 return 180. 0xb2 getstatic 181. 0xb3 putstatic 182. 0xb4 getfield 183. 0xb5 putfield 从当前方法返回 int 从当前方法返回 long 从当前方法返回 float 从当前方法返回 double 从当前方法返回对象引用 从当前方法返回 void 获取指定类的静态域,并将其值压入栈顶 为指定的类的静态域赋值 获取指定类的实例域,并将其值压入栈顶 为指定的类的实例域赋值 调用实例方法 调用超类构造方法,实例初始化方法,私有方法 调用静态方法 184. 0xb6 invokevirtual 185. 0xb7 invokespecial 186. 0xb8 invokestatic 187. 0xb9 invokeinterface 调用接口方法 188. 0xba -189. 0xbb new 190. 0xbc newarray 入栈顶 191. 0xbd anewarray 创建一个引用型(如类,接口,数组)的数组,并将其引用值压入栈顶 将栈顶的异常抛出 检验类型转换,检验未通过将抛出 ClassCastException 获得对象的锁,用于同步方法或同步块 释放对象的锁,用于同步方法或同步块 192. 0xbe arraylength 获得数组的长度值并压入栈顶 193. 0xbf athrow 194. 0xc0 checkcast 创建一个对象,并将其引用值压入栈顶 创建一个指定原始类型(如 int, float, char…)的数组,并将其引用值压 195. 0xc1 instanceof 检验对象是否是指定的类的实例, 如果是将 1 压入栈顶, 否则将 0 压入栈顶 196. 0xc2 monitorenter 197. 0xc3 monitorexit 198. 0xc4 wide <待补充> 199. 0xc5 multianewarray 创建指定类型和指定维度的多维数组(执行该指令时,操作栈中必须包 含各维度的长度值),并将其引用值压入栈顶 200. 0xc6 ifnull 201. 0xc7 ifnonnull 202. 0xc8 goto_w 203. 0xc9 jsr_w 为 null 时跳转 不为 null 时跳转 无条件跳转(宽索引) 跳转至指定 32 位 offset 位置,并将 jsr_w 下一条指令地址压入栈顶。

相关文档
最新文档