在开发中我们有时会遇到这样的场景,需要修改 jar 包内某个 class ,常见的方法就是先解压缩,然后反编译这个 class ,新建 java 修改再编译,最后再打包,整个过程是非常耗时的。
这里向大家介绍一款 IDEA 插件:JarEditor ,可以一键修改 JAR 包内文件,无需解压。
首先在插件商城搜索 JarEditor ,可直接安装插件
安装完后,任意打开一个 jar 的 class ,可以看到反编译后的 class 内容,选中 Jar Editor 的 tab 页签,就可以直接编辑 class 了
修改完代码后先点击 Save,这个过程会编译 class ,编译成功后点击Build Jar就修改 jar 完成了,是不是很简单?下面是一个修改的例子。
SDK 可以选择需要的 JDK 或者其他 SDK ,Target 为编译 class 的目标版本,默认是和反编译的 class 前的版本保持一致。
选择 File->Project Structure->Libraries ,然后添加工程外的 jar 即可打开 jar 内文件修改
也可以将 jar 包粘贴到本项目中,然后右键->Add as Library...
操作流程同修改 class 文件,不需要选择 Compile
在工程视图 jar 包内某个文件夹上右键->JarEditor->New,可以新建 Class/Kotlin/File/Directory
选择后输入文件名即可在 jar 内新增文件,默认是空文件
新增后打开可以写入内容,Class 和 Kotlin 新建完文件是有模版的,无需后缀名,如果是 JarEditor->New->File 则需要写文件后缀名。
在工程视图 jar 包内某个文件或者文件夹上右键->JarEditor->Delete,则会删除选择的目录或者文件,支持多选。
在工程视图 jar 包内某个文件或者文件夹上右键->JarEditor->Rename,输入名字后即可将原来的名字修改为新的名字,修改完立即生效。
在工程视图 jar 包内某个文件或者文件夹上右键->JarEditor->Copy,可以将 jar 包内文件拷贝到剪切板(支持多选)
然后在外部任意一个文件夹内,使用 Ctrl+V ,即可将刚才复制的文件拷贝到这个目录
外部文件使用 Ctrl+C 复制后,在 jar 内某个文件夹上右键->JarEditor->Paste(不能直接用 Ctrl+V ,Ctrl+V 被 IDEA 默认占用了),即可将剪切板的文件粘贴到 jar 包内,一气呵成。
工具栏有一个搜索图标,点击后输入需要搜索的字符串,可搜索到 jar 包内的文件,包括 class 和普通文件。
点击搜索后的文件列表,可跳转到具体的文件
搜索的 class 如果是 class jar 的话取决于反编译的内容,如果是 source jar 取决于 java 文本。
IDEA 内打开的 jar 分两种,class jar 和 source jar ,如果下载了源码的话,打开的是 source jar ,即打开的是一个 java 文件,而不是 class 文件,这里一定要注意
此时如果修改代码的话,生效的是 source jar ,比如这里改的是 FindInstancesOfClass-1.0.3-sources.jar 。
点击 JarEditor Tools 上面的跳转链接:Click hear to open class jar 即可跳转到 class 文件
此时展示的 class 为反编译的代码,可修改 class 文件,按 修改 class 文件 的流程操作即可。
也可以从 source jar 中导入代码:Import from source jar
Import from source jar 和直接在 souce jar 中的 java 修改的区别是:前者修改的是 class jar 后者是 source jar 。
目前支持 java 和 kotlin 两种文件编译,后续可能会增加更多的编译文件支持。
选择 SDK Default 时,是使用的 IDEA 运行时自带编译器,即 javax.tools.JavaCompiler,详细可阅读源码。
选择其他 JDK 时,默认使用的是 javac 外部命令编译。
编译时选择的 Target 的范围是 1.1~所有 JDK 的版本最大值。
考虑到可能会修改多个文件,会将当前修改的内容(编译)保存到所在 jar 包目录的临时目录 jar 名_temp/jar_edit_out 下,当点击 Build Jar 将增量文件写入 jar 后,会删除临时目录,也可手动清理临时目录。
在编译时,依赖的 jar 为当前工程的 Libraries ,如果编译时提示依赖包找不到,可以添加依赖即可。
另外 class 文件的内容取决于反编译的结果,如果混淆的代码则不太方便修改和编译。
当选择 SDK Default 编译时,对应的 JDK 版本如下:
IDEA | JDK |
---|---|
IDEA 2020.3 ~ IDEA 2022.1 | JDK 11 |
IDEA 2022.2 ~ IDEA 2024.1 | JDK 17 |
IDEA 2024.2 及更高版本 | JDK 21 |
本文主要介绍了使用 JarEditor 直接对 jar 包文件进行增删改查操作,简化了修改 jar 的流程,感兴趣的朋友可以去试试。
本文篇幅有限,具体原理和实现细节可阅读源码
1
wxw752 137 天前
从业八年没有遇到过这么改的场景😅
|
2
designer 136 天前 via iPhone
想起了以前诺基亚手机玩 java 游戏,修改 QQ jar class 文件
|
3
kandaakihito 136 天前
@wxw752 一些依赖在特定环境下会遇到奇葩的 bug ,比如 jco3 ,每次都得打包完进去改点东西
|
4
Aresxue 136 天前
蛮不错的插件,就是编译可以再扩充一些,一个是可以指定电脑本地的其它 jdk ,甚至一些三方的反编译和编译库像 cfr 、Procyon;另一个是我没看到对三方库的处理,指原不在我当前应用中的三方包但我本次修改需要使用的三方库,这块处理也确实会比较麻烦但在这个魔改 jar 的场景里面出现的概率却并不低。
|
5
liubsyy OP @Aresxue 指定 JDK 是有的,最新版 SDK 可以添加和选择其他 JDK 。现在反编译是 IDEA 默认的 Fernflower ,后续可以考虑其他反编译库的支持。第三方库是指的不在项目中的 jar 但是需要依赖的么?可以手动添加外部 Libraries 就能在 External Libraries 看到了
|
7
Aresxue 136 天前
@liubsyy 我的意思是你的发布物是什么样的,原先不依赖的新三方库我理解就是导出一个新的 jar 包就叫它 newbiz.jar 好了,把这个 jar 包在容器里面替换掉原有的 biz.jar 然后重启 java 进程就生效了,新依赖三方包的话新的三方包你是会直接打到 newbiz.jar 中还是说是分开的,除了替换原有的 biz.jar 以外还需要再上传一个 third.jar ,值得注意的是这个 third.jar 可能以前已经有低版本的了这里再引入一个会面临业务里面会遇到的钻石依赖问题。
|
8
nikelei 136 天前
bd
|
10
lovedoing 136 天前
试了下挺好用的
|
11
ppooqq 129 天前
挺好的,不知道能不能实现以下功能:
1 、有项目二开的,一部分 jar 没有源码,希望支持全局在 idea 里搜索这些 jar 包的内容。通过插件是可以对单个 jar 进行搜索,但前提要猜到想找的方法,关键字在哪个 jar 包里。 2 、能批量将依赖中的多个无源码的 jar 包反编译并生成-source.jar ,并存放在相同目录,这样 idea 就认为是有源码可以搜索了。 |