修改jar文件中class的包路径
admin 发布于:2026-05-16 15:20:30
阅读:loading
在很多时候有需要去修改jar文件中class所在包路径的需求,本文围绕的是这一个需求的实现开展的科学实践。记得在2025年4月份从CSDN下载了一份Spire.Doc for Java科学后的jar文件,正当我准备向这份资源的作者大佬学习的时候,主要是想了解究竟修改了哪个位置的class后,才发现不仅是某些class被修改了,更牛的是整个产品的包路径全都被修改过了,所以对比着查看jar文件的class内容时,所有的class都是存在差异的,估摸着这是作者大佬想保护自己的心血吧,以所有class文件都修改的方式来大大增加他人查看具体如何科学这款产品的复杂度与难度吧,所以我的疑问不仅是它究竟是如何科学的这款产品,更使我有兴趣的是他是如何修改的jar文件中的class文件的包路径的呢,所以时隔一年多,困扰我的这个问题终于被我掌握了。
比如说有这二种场景可以通过修改jar文件中class的包路径来实现:
(1)假如说在一个老旧项目中使用到了比较多的操作共享服务器的jcifs技术,假如共有10个模块的功能均使用到了,涉及功能较多,范围较广,而只有1-2个功能模块情况特殊必须要通过升级jcifs组件来解决,如果你了解jcifs组件的话,你清楚新版本与旧版本的包路径是一样的,但是API使用不同,新版并不兼容旧版本,此时你行之有效的方法是将jcifs组件进行升级,无论耗时费力与否,起码涉及到的功能范围比较大,稍微一个不注意就容易带来线上问题;这种场景我推荐的做法是找到jcifs的新版本jcifs-ng,下载其源代码后重新编译打包,更改包路径,使得在项目中可以同时并存新旧版本的两个jcifs组件,这样的话功能运行正常的就不需要改动,只需要调整特殊有问题的功能即可,但是有一点需要注意的是,自行修改jar的包路径重新编译打包是需要有源代码的;
(2)比如你的项目中使用到了一些商业性质的产品(该获取授权就获取授权)gif4j,商业性质的产品组件不会对外提供源码,并且jar文件内部的class也存在较多的加密和混淆,也就是说你拿到手的只有一些jar文件,恰好你觉得在你的项目代码中存在商业产品的关键字(也就是import的一些package路径如:com.gif4j)甚为不妥,这时就可以使用本文所述的专业的手段来进行包路径的改写,比如修改成“org.apache.gif4j”相关的字样;
上面白话说了一堆不知道我要表达的意思有没有说清楚,大概可以看看下面这个图片,这是前文说的从CSDN上下载的大佬更改过的jar文件,大佬把原始的com.spire.doc的包路径修改成了com.sini.com.spire.doc的路径,这么一修改相当于直接修改了全部的class文件,如果你期望对比这些class来轻易的找到大佬破解这款产品时究竟修改了哪些地方时,难度相当的大,比较需要把jar包中全部的class文件都对比一下,参考如下图所示:

初次看到这一大作,让我感觉相当的高端,这是怎么做到的呢,当然也可以把com.spire.doc修改为org.github.doc,避免在你所使用的地方出现某些关键字,所以我也经常的思考这是怎么做到的,甚是不解,也经常的利用业余时间进行一次又一次不间断的摸索,终于就有了本篇文章的实践总结,所以我实践的具体方案是:
(1)使用到了一些字节码框架,比如ASM和javassist,重点是后者吧,虽然可以实现将一个jar包中所有的package路径按需修改,但是对于一些import的包则是没有正常的修改成功,也许是摸索的时间和深度有所欠缺吧,没有达到预期理想的结果;更为重要的是如果是自己写更改程序的话,那就更加不稳定;
(2)在文了一些AI大模型后,告诉我Maven的插件maven-shade-plugin可以,重点了解到的是基于有源码的情况下,将源码中的包路径给重命名,打包成一个新的jar,实际我更加期望的是将无源码的jar包给更改,所以我真就不信任这个插件,后来也是耐着性子把这个插件给配置上,结果还真就可以做到,符合我的期望,重点就是他,比自己写程序更加稳健;
新建一个IDEA的Maven项目,使用JDK8,以Apache开源的Commons Lang3的工具包为例进行包路径的修改,原因有以下几个方面:
(1)开源免费,与世无争吧;
(2)正好验证在更改jar包路径的时候会不会同时下载依赖源码,也就是看看会不会下载commons-lang3的javadoc.jar;
本次实践还是同时使用多个jar进行修改吧,除了Commons Lang3以外,再增加fastjson吧,同时验证多个组件包的修改,显得更加专业,参考关键代码如下:
<relocations>
<relocation>
<!-- 原始包路径 -->
<pattern>org.apache.commons.lang3</pattern>
<!-- 目标包路径 -->
<shadedPattern>cn.chendd.commons.lang3</shadedPattern>
<!-- 排除不被重命名的类 -->
<excludes>
<exclude>org.apache.commons.lang3.exception.ExceptionUtils</exclude>
<exclude>org.apache.commons.lang3.time.DurationUtils</exclude>
</excludes>
</relocation>
<relocation>
<pattern>com.alibaba.fastjson</pattern>
<shadedPattern>cn.chendd.fastjson</shadedPattern>
</relocation>
</relocations>代码说明
(1)修改commons-lang3的包路径“org.apache.commons.lang3”修改为“cn.chendd.commons.lang3”;
(2)不修改“org.apache.commons.lang3.exception.ExceptionUtils”这个类;
(3)不修改“org.apache.commons.lang3.time.DurationUtils”这个类;
(4)修改fastjson的包路径“com.alibaba.fastjson”为“cn.chendd.fastjson”;
再有了上面的Maven项目后,直接使用Maven打包的形式来生成我们期望的新的jar包,也就是“mvn clean package”命令,也可以在IDEA上使用Maven面板的按钮生成,所以打包后的文件结构参考如下:

(打包生成jar)
图片说明
(1)新生成的jar文件包含了cn.chendd.commons.lang3的包路径;
(2)新生成的包路径中包含了commons、fastjson两款组件的组合包;
(3)新生成的包路径中另有commons/lang3/exception和commons/time的包,这两个包中的工具类仍然是原始的jar包路径,等于说验证了排除了一些不变更的类;

(修改引用结果)

(修改排除类的结果)
(1)本次实践的结果有特定使用的场景,并非常规技术分享,对于有用的时候应该是真的很有用;
(2)上面的所述打包生成的jar文件并未实际的进行二次代码验证,也就是说并未使用它导入项目,进行cn.chendd.commons.lang3.StringUtils等一系列工具类的使用,验证其正确使用的结果;
(3)本身本次实践的也是开源的组件,在对应的Maven私服坐标下也并未级联下载对应的源码jar包,也就是java-source.jar;
(4)实际上本次实践了另外一款商业性质的PDF组件,这款组件内部更为复杂,jar包中包含了class的混淆和加密,所以我验证了它,结果是理想的;
(5)给出《
源码下载.zip》,完整的代码示例,非常简单,当然了更多更深层、更专业的我属实是不愿意再花费更多的时间了;
(6)特别说一点,对于那种最为复杂的商业性质的jar,其中jar里面的包路径与class文件名称相同,且class又存在同名的大小写,等等等等,非常非常非常的复杂,我这里更加不愿意去验证了,耗时费力的,结果还不一定理想,就到这里打住吧;
点赞
欢迎来到陈冬冬的学习天地 | 学习与经验整理分享平台