2023年12月2日发(作者:)
读取jar包中嵌套的jar包内容的方法背景最近在做 javaagent 的时候,我们需要将很多依赖的包打成一个大大的 jar 包,这时候可以用maven-shade-plugin 进行操作,但是如果我们的代码不想默认被 AppClassloader 来加载(javaagent 的代码默认是由 AppClassloader 来进行加载的),又不想将这些包放在这个大 jar 包的外面,这个时候我们就需要吧这些代码以 jar 包的形式放在 resources 里面,最终 jar 包图可能是这样.── org ├── ── plugins ├── ├── ├── ...复制代码org 文件夹里面存放的是我们编译后的.class 文件, plugins 存放的是一些需要额外加载的 jar 包,默认情况下,里面的代码是当前classloader 加载不到的,需要自定义 classloader 来加载.如何加载但是如何来加载jar 包里面的文件呢?假如外面这层 jar 包的名字为. 你可能会自定义一个 classloader, 加入有个 位于 中,自定义 classloader 当然需要覆写 findClass 方法,如何把这个文件加载到内存呢?思路1我们都知道对于读取 jar 包里面的路径都有特定的格式,比如读取 的 jarEntry可以这样读取 JarFile jarFile = new JarFile(new File("")); Enumeration
} return folder; } catch (Exception e) { (" unpack to folder error", e); throw new RuntimeException(e); } }// 解压 jar 包; private static void unpack(JarFile jarFile, JarEntry entry, File file) throws IOException { try (InputStream inputStream = utStream(entry)) { try (OutputStream outputStream = new FileOutputStream(file)) { byte[] buffer = new byte[BUFFER_SIZE]; int bytesRead; while ((bytesRead = (buffer)) != -1) { (buffer, 0, bytesRead); } (); } } }复制代码其实我们最终获取到TEMP_FOLDER其他操作都像读文件一样了,关键在于如何解压,这里面的几个小细节:OnExit(); 的使用,相当于给文件删除注册了一个钩子,当 JVM 退出的时候,自动回删除这个文件,最终被删除的文件是保存在一个队列里面的,所以这里的删除代码顺序注册也是有讲究的.每次创建的文件夹都不一样,避免污染环境,读取的文件过多或者过少.直接读取虽然不能随意读取嵌套jar 包中的内容,但是JarFileEntry 中可以读取manifest 文件,我们可以一些需要读取的放在这个文件里面,然后在外面直接读取.public synchronized Manifest getManifest() throws IOException {}复制代码引用ps: 除了临时目录的方法,可能还有更好的方法.


发布评论