如果出于某些原因,需要修改第三方jar包里的class文件,我们能有什么办法呢?
直接修改肯定是运行不了的,这里我给大家介绍一个小工具jclasslib,因为我的电脑是64位的,所以这里就安装64位版
下载地址:https://github.com/ingokegel/jclasslib/releases/download/5.5.1/jclasslib_win64_5_5_1.exe
源码:https://github.com/ingokegel/jclasslib
版本系列:https://github.com/ingokegel/jclasslib/releases
jclasslib引用包,主要用在修改class的项目工程里
https://download.youkuaiyun.com/download/suwei825/15893593
一、安装
一路选择next,最后安装成功 Finish!
二、使用
接下来介绍下怎么使用这个工具,我准备了一个测试程序,我们熟悉的hello world
我们新建一个maven项目,添加一个类,里面是一个main主方法
public class testjclass {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String str="Hello World!";
System.out.println(str);
}
}
执行maven打包后,我们得到一个jar包
命令行执行
我们把jar用压缩软件解压
接下来我们运行刚才安装好的jclasslib_win64_5_5_1
我们打开刚才解压的class文件
得到如下界面,我们展开methods菜单
我们点击code
就会显示java类的字节码了,我们看第一行,实际就是我们的hello world
我们点击 #2,可以转到常量池
我们再点击cp info #23,就找到hello world了
以后遇到第三方jar需要修改,我们编写一个新的java文件
引用的包,从我上面提供的jclasslib引用包下载地址下载,我们在项目根目录建一个lib目录,把包放进去,我这里用的IDEA Java编程工具
pom文件加依赖,注意引用的是本地项目目录${project.basedir}
<dependency>
<groupId>org.gjt.browser</groupId>
<artifactId>jclasslib-browser</artifactId>
<version>5.5.1</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/jclasslib-browser.jar</systemPath>
</dependency>
<dependency>
<groupId>org.gjt.jclasslib</groupId>
<artifactId>jclasslib-browser</artifactId>
<version>5.5.1</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/jclasslib-library.jar</systemPath>
</dependency>
<dependency>
<groupId>org.gjt.kotlin-runtime</groupId>
<artifactId>kotlin</artifactId>
<scope>system</scope>
<systemPath>${project.basedir}/lib/kotlin-runtime-1.0.6.jar</systemPath>
</dependency>
<dependency>
<groupId>org.gjt.kotlin-stdlib</groupId>
<artifactId>kotlin</artifactId>
<scope>system</scope>
<systemPath>${project.basedir}/lib/kotlin-stdlib-1.0.6.jar</systemPath>
</dependency>
下面贴出修改代码
import com.sun.org.apache.bcel.internal.util.ClassPath;
import java.io.*;
import org.gjt.jclasslib.io.ClassFileWriter;
import org.gjt.jclasslib.structures.ClassFile;
import org.gjt.jclasslib.structures.Constant;
import org.gjt.jclasslib.structures.constants.ConstantDoubleInfo;
import org.gjt.jclasslib.structures.constants.ConstantUtf8Info;
import org.gjt.jclasslib.structures.constants.ConstantStringInfo;
public class edit {
public static void main(String[] args) throws Exception {
String filePath = "D:\\swjava\\ss-1.0-SNAPSHOT\\testjclass.class";
FileInputStream fis = new FileInputStream(filePath);
DataInput di = new DataInputStream(fis);
ClassFile cf = new ClassFile();
cf.read(di);
Constant[] infos = cf.getConstantPool();
int count = infos.length;
for (int i = 0; i < count; i++) {
if (infos[i] != null) {
if(i==23){
ConstantUtf8Info uInfo = (ConstantUtf8Info) infos[i]; //刚刚那里是CONSTANT_Utf-8_info所以这里要用这个
uInfo.setString("你好程序世界!");
infos[i] = uInfo;
}
}
}
cf.setConstantPool(infos);
fis.close();
File f = new File(filePath);
ClassFileWriter.writeToFile(f, cf);
}
}
这里我把helloworld改成了你好程序世界!
我们编译后不报错就可以了,在代码中配置的 filePath 目录D:\\swjava\\ss-1.0-SNAPSHOT\\里,我们看testjclass.class这个文件的修改日期,就会发现这个文件已经被修改了
接下来就简单了,我们把testjclass.class替换原来jar包的class文件,有2种方式
1、解压被修改的jar包,在相应class位置覆盖原来class文件,然后把解压目录再压缩为zip格式的压缩包,把zip后缀改jar后缀
2、用压缩工具直接打开要修改的jar包,把修改了的class文件直接拖进去覆盖
这里我推荐第2种方法,因为第一种我测试会报错,而且发现第一种解压后再压缩,jar的大小变化很大,可能破坏了结构和压缩率之类的,导致不能运行。
我们再执行java -jar ss-1.0-SNAPSHOT.jar,就会输出修改后的内容了