背景
最近在做 javaagent 的时候,我们需要将很多依赖的包打成一个大大的 jar 包,这时候可以用maven-shade-plugin
进行操作,但是如果我们的代码不想默认被 AppClassloader 来加载(javaagent 的代码默认是由 AppClassloader 来进行加载的),又不想将这些包放在这个大 jar 包的外面,这个时候我们就需要吧这些代码以 jar 包的形式放在 resources 里面,最终 jar 包图可能是这样.
── org
├── Hello.class
── plugins
├── a.jar
├── b.jar
├── c.jar
...
复制代码
org 文件夹里面存放的是我们编译后的.class
文件, plugins 存放的是一些需要额外加载的 jar 包,默认情况下,里面的代码是当前 classloader 加载不到的,需要自定义 classloader 来加载.
如何加载
但是如何来加载jar 包里面的文件呢?假如外面这层 jar 包的名字为demo.jar
. 你可能会自定义一个 classloader, 加入有个 World.class
位于 a.jar 中,自定义 classloader 当然需要覆写 findClass 方法,如何把这个文件加载到内存呢?
思路1
我们都知道对于读取 jar 包里面的路径都有特定的格式,比如读取 a.jar 的 jarEntry可以这样读取
JarFile jarFile = new JarFile(new File(""));
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement();
String name = jarEntry.getName();
if("plugins/a.jar".equals(name)){
.....
}
}
复制代码