对于Java程序员来说,工作中经常会遇到这样一些问题,比如引用了些第三方提供的非开源jar包,这个时候我们需要用它,甚至需要改它的内容。怎么办?下面看看开发中会遇到哪些问题?
- 某个类的里面的字段默认值不符合需求要改掉.
- 某个方法里面有很多校验,想直接return ;绕过校验。
- 某个方法里面的计算方法太复杂,想用自己的计算方式。替换方法体。
- 首先声明一点,如果是收费的,切勿参加商业性质。
往往这个时候我们就会很棘手,因为确实不好操作,不好处理。现在我给大家介绍两种方式,解决一些比较常见且简单的问题。
1、反编译class文件,推荐Java Decompiler
这个工具几乎能正确的反编译出源代码。如果反编译出的源码,没有出现很明显的错误。或者说很难修改的错误时。通常这个时候我们直接修改该类已达到我们的需求就可以了,把修改后的class文件覆盖jar里的class文件,即可。
不过,有时候第三方提供的jar里面,某些类写的特别复杂,反编译后一堆错误,真的没法修改。这个时候可以试试第二种方法。
2、利用工具直接修改class字节码,推荐Javassist
先给大家介绍一下Javassist,Javassist是一个开源的分析、编辑和创建Java字节码的类库,它已加入了开放源代码JBoss 应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态AOP框架。
关于java字节码的处理,目前有很多工具,如bcel,asm。不过这些都需要直接跟虚拟机指令打交道。如果你不想了解虚拟机指令,可以采用javassist。javassist是jboss的一个子项目,其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。
1、我们可以用Javassist实现什么。
- 添加修改父类
- 添加修改方法
- 添加修改字段
- 创建类
2、准备工作
2.1首先下载Javassist,jar文件
2.2获得ClassPool对象,他控制者class字节码的修改。
ClassPool pool = ClassPool.getDefault();
2.3.如果你准备修改的class文件在某个路径或者jar文件里或者网络的某个路径。需要设置路径
1
2
3
4
5
6
7
|
pool.insertClassPath( "E:\\test" );或者提供一个jar文件
pool.insertClassPath( "E:\\test.jar" );或者提供一个网络路径
ClassPath cp = new URLClassPath( "www.javassist.org" , 80 , "/java/" , "org.javassist." );
pool.insertClassPath(cp);或者直接提供 byte 字节码
byte [] b = a byte array;
String name = class name;
pool.insertClassPath( new ByteArrayClassPath(name, b));
|
2.4.下面我们就要处理class文件了,每个class文件对应一个CtClass对象,而CtClass是从对象ClassPool对象里得到。需要完整的包名+类名,不需要.class
1
|
CtClass cc = pool.get( "com.my.TestMain" );
|
2.5.完整代码
1
2
3
4
|
ClassPool pool = ClassPool.getDefault(); //pool.insertClassPath("E:\\test.jar");
pool.insertClassPath( "E:\\test" );
CtClass cc = pool.get( "com.my.TestMain" );
|
3、添加修改父类
3.1.添加接口
cc.setInterfaces(new CtClass[] { pool.get("com.my.TestMain2") });
3.2.添加抽象类
1
2
|
cc.setSuperclass(pool.get( "com.my.TestMain1" ));
cc.writeFile(); |
如果父类已经存在就用现在的类替换了。
4、添加修改方法
4.1.添加新的方法
1
2
3
4
|
CtClass cc = pool.get( "sample.TestMain" );
CtMethod cm = CtNewMethod.make( "public void toInt(int i){i++;}" , cc);
cc.addMethod(cm); cc.writeFile() |
4.2.修改方法
1
2
3
|
CtClass cc = pool.get( "sample.TestMain" );
CtMethod cm = cc.getDeclaredMethod( "toInt" , new CtClass[]{ CtClass.intType });
cc.writeFile(); |
getDeclaredMethod的第一个参数是方法名,第二个参数是方法的参数。
获得方法对象后,以下三种方法是最常用的。
- cm.setBody("");重新设置方法体
- cm.insertBefore("");在原来方法的最前面插入代码
- cm.insertAfter("");在原来方法的后面插入代码
4.3.删除方法
1
|
cc.removeMethod() |
5.添加修改字段
5.1.添加字段
1
2
3
4
5
|
//方式1 CtClass cc = pool.get( "sample.TestMain" );
CtField f = new CtField(CtClass.intType, "t1" , cc);
cc.addField(f, "2" ); // initial value is 0.
cc.writeFile(); |
//方式2
1
2
3
4
|
CtClass cc = pool.get( "sample.TestMain " );
CtField f = CtField.make( "public int z = 0;" , point);
cc.addField(f); cc.writeFile(); |
5.2.修改字段,方法里没有提供直接修改,我们需要删删除在修改
1
2
3
4
5
|
CtClass cc = pool.get( "sample.TestMain" );
CtField f = cc.getDeclaredField( "t" );
cc.removeField(f); cc.addField(CtField.make( "public int t=3;" , cc));
cc.writeFile(); |
6.创建新类
1
2
3
|
ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.makeClass( "Point" );
cc.writeFile(); |
7.Import
1
2
3
4
|
ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.makeClass( "sample.TestMain" );
pool.importPackage( "java.awt" );
cc.writeFile(); |
jar包在附件中
相关推荐
Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...
可移植性:Java字节码可以在所有安装了JVM的设备上执行,从服务器到嵌入式系统,再到移动设备和桌面应用。 健壮性与高性能:Java通过垃圾回收机制确保内存的有效管理,同时也能通过JIT编译器优化来提升运行时性能...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
北京动力节点-Java编程零基础教程-011-Java语言概述-Java的工作原理-源文件及字节码文件.mp4 北京动力节点-Java编程零基础教程-012-Java语言概述-Java的工作原理-JVM分类.mp4 北京动力节点-Java编程零基础教程-...
Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
可移植性:Java字节码可以在所有安装了JVM的设备上执行,从服务器到嵌入式系统,再到移动设备和桌面应用。 健壮性与高性能:Java通过垃圾回收机制确保内存的有效管理,同时也能通过JIT编译器优化来提升运行时性能...
3. 反射和字节码操作:学习使用Java的反射机制和字节码操作库,实现动态代理、代码生成和运行时修改类的功能。 4. 函数式编程:学习Java 8及更高版本引入的函数式编程特性,如Lambda表达式和Stream API,提升代码...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
基于javadbf-0.4.0修改而来,a.修改了基类中的默认字符编码;b.修改了写入类中的字节填充位置计算方法,使之支持双字节; 补充:通常dbf使用excel打开时,gb2312的中文能正常显示,utf8的不行,所以默认字符集设置成...