URLClassLoader热加载、卸载,自定义热加载数据池 jar包(附:Springboot + Hutool-db 使用实例)

本文介绍了如何使用URLClassLoader实现Java中jar包的动态加载和卸载,探讨了在不同环境下遇到的问题及解决方案,包括切换ClassLoader获取方式以避免找不到类的错误,并提供了相关代码示例。
摘要由CSDN通过智能技术生成

参考文章:
利用classloader实现jar包的加载和卸载,实现类的热替换
动态添加classpath
关于ClassLoader.getSystemClassLoader()和Thread.currentThread().getContextClassLoader()
老大难的 Java ClassLoader 再不理解就老了
关闭URLClassLoader打开的jar包

前言


过程

最近在做动态加载数据驱动和数据池的部分,网上多是使用URLClassLoader 作为动态加载jar的,但是经过多天的百度和测试,都未能成功,很多情况下都给出了类似 动态添加classpath 这篇文章的例子,这些例子在测试环境是能正常使用的,但到部署环境,又会出现各种问题,而且想实现卸载,会有些麻烦,详情参考 关闭URLClassLoader打开的jar包 这篇文章,直接使用URLClassLoader.close(),会出现其他jar包读取不了的问题。而且这种卸载,测试的时候,也出现了不能重载的现象。

然后看到 利用classloader实现jar包的加载和卸载,实现类的热替换 这篇文章,参考这篇文章内容进行相应更改,成功在测试环境正常热加卸载。但是到了部署,还是会出现找不到的问题。不过这篇文章的优点在于他把jar包自行保存了一份,这样就不用像 关闭URLClassLoader打开的jar包 这篇文章那样,需要通过复杂过程获取jar包关闭,这个方法很好,所以保留在我的代码里了。

直到看到 关于ClassLoader.getSystemClassLoader()和Thread.currentThread().getContextClassLoader() 这篇文章,详细解决原因,请看原文,更换了classloader获取方式,终于成功在测试和部署上都成功热加卸不报错了。

你以为这就成功了?不是的,虽然加载卸载没问题,但是要使用这个数据池的时候,他会报找不到其他jar所需的class(例如 log4j2 )。嗯,心态崩溃了。

反正各种沉默后,突然灵光一现,可能是级别不够,找不到位?不知道怎么解析,反正我是这样想的,然后给Thread.currentThread().getContextClassLoader()加了个爸爸,变身Thread.currentThread().getContextClassLoader().getParent(),终于成功了。之前的报错,都没出现了。狂奔

都是自己对ClassLoader的不熟悉,导致各种问题出现,所以推荐大家看一下 老大难的 Java ClassLoader 再不理解就老了 这篇文章,虽然我暂时还没理解透

最后总结一句,ClassLoader 爸爸虽然懒,但是也经不起我的折腾


代码

  1. exJarEntity.java:用于保存对应jar包信息
package chen.wset.entity;

import lombok.Data;

import java.io.Serializable;
import java.net.URLClassLoader;
import java.util.jar.JarFile;

//用于保存对应jar包信息
@Data
public class exJarEntity implements Serializable {
   
    // 驱动名
    String name;
    // 驱动url
    String url;
    // URLClassloader
    URLClassLoader urlClassLoader;
    // 驱动jar包,用于关闭对应jar
    JarFile jarFile;
}

  1. dynamicLoading.java:加载、卸载、获取 jar - classloader 操作
package chen.wset
你可以使用URLClassLoader类来加载Jar包里面的Jar包。首先,你需要创建一个URLClassLoader对象,并将需要加载Jar包的路径传递给它。然后,你可以使用ClassLoader对象来加载Jar包中的类或资源。 以下是一个示例代码,演示了如何使用URLClassLoader加载Jar包里面的Jar包: ```java import java.net.URL; import java.net.URLClassLoader; public class Main { public static void main(String[] args) throws Exception { // 定义需要加载Jar包路径 String jarPath = "path/to/your/jar/file.jar"; // 创建URL数组,包含需要加载Jar包路径 URL[] urls = new URL[]{new URL("file:" + jarPath)}; // 创建URLClassLoader对象,将Jar包路径传递给它 URLClassLoader classLoader = new URLClassLoader(urls); // 加载Jar包中的类 Class<?> loadedClass = classLoader.loadClass("com.example.SomeClass"); // 创建该类的实例,并调用方法 Object instance = loadedClass.getDeclaredConstructor().newInstance(); loadedClass.getMethod("someMethod").invoke(instance); } } ``` 在上述代码中,你需要将"path/to/your/jar/file.jar"替换为实际的Jar包路径。然后,你可以使用URLClassLoader对象加载Jar包中的类,并调用其中的方法。 请注意,加载嵌套的Jar包可能会导致一些类加载问题,因此你可能需要注意处理这些问题。此外,记得在使用URLClassLoader后,关闭它以释放资源。 希望对你有所帮助!如有更多问题,请随时提问。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值