classloader.loadclass()找不到类主因是路径不匹配,仅搜索classpath;需用urlclassloader显式添加jar路径,依赖类也须加入classpath,且loadclass不触发静态初始化,应改用class.forname(name, true, cl)。

ClassLoader.loadClass() 为什么找不到类文件
直接调用 loadClass() 失败,多数是因为路径没对上——它只认 classpath 下的资源,不处理任意文件路径或 jar 包内嵌路径。比如你把 plugin.jar 放在 ./ext/ 目录下,loadClass() 默认根本不会去扫这个目录。
- 必须用
URLClassLoader构造时显式传入URL,例如new URLClassLoader(new URL[]{new File("ext/plugin.jar").toURI().toURL()}) - 如果类依赖其他类(比如用了
org.apache.commons.lang3.StringUtils),这些依赖也得一并加进 classpath,否则运行时报NoClassDefFoundError -
loadClass()不会触发静态初始化块,需要主动调用Class.forName(name, true, cl)才行
如何安全卸载动态加载的类
Java 没有“卸载类”的 API。所谓“卸载”,本质是让 ClassLoader 实例及其加载的所有类能被 GC 回收——前提是这个 ClassLoader 不再被任何地方引用,且它加载的类也没被静态变量、线程栈、JNI 引用等持有着。
- 别把动态加载的
Class或实例存到全局 static 字段里 - 用完后清空自定义
ClassLoader的强引用(比如设为null),并确保没有线程还在用它创建的对象 - 常见陷阱:用
Thread.setContextClassLoader()切换后忘了切回去,导致老 ClassLoader 被线程长期持有 - JVM 参数
-XX:+TraceClassUnloading可验证是否真卸载了(日志里出现unloaded)
getResourceAsStream() 返回 null 的真实原因
这不是 ClassLoader 有问题,而是资源路径语义和文件系统路径不一致。比如你在代码里写 cl.getResourceAsStream("config.json"),它实际查找的是以 / 开头的类路径根目录下的 config.json,不是当前目录,也不是 src/main/resources 的相对路径。
这是一个免费的企业网站系统,任何人可以免费下载、修改和使用本程序,也可以用来为企业建网站。没有任何功能限制,且不发布收费版。容兴免费企业网站系统后台功能简介:1.基本设置:基本信息,联系方式,网站设置,导航管理,模块启闭,静态设置,安全设置,数据库管理2.产品管理:产品列表,添加产品,产品分类3.文章管理:文章列表,发表文章,文章分类,公司简介,网站公告4.客服互动:留言管理,在线客服,友情链接5
- 路径不能以
/开头(除非你明确想从 classpath 根查),否则会被当成绝对路径跳过 package 前缀逻辑 - jar 包里的资源必须用
getResourceAsStream(),不能用new FileInputStream()—— 后者读不了 jar 内部文件 - 如果资源在子包里,比如
com/example/plugin/config.json,路径就得写成"com/example/plugin/config.json",不是"./config.json" - 注意 IDE 编译后资源可能被复制到
target/classes/,但打包时若没配maven-resources-plugin,可能漏掉
双亲委派被绕过的典型场景
自定义 ClassLoader 默认仍走双亲委派,想加载自己 jar 里的 log4j-core 却意外用了 JDK 自带的 java.util.logging,就是因为父加载器抢先返回了同名类。
立即学习“Java免费学习笔记(深入)”;
- 重写
loadClass(String name, boolean resolve)时,不要直接 super.loadClass(),先 try 自己 findClass(),失败再委托 - 绕过委派要小心冲突:比如你加载了新版
fastjson,但某个框架通过系统类加载器加载了旧版,两者混用可能报LinkageError - OSGi 或 Spring Boot DevTools 的类隔离,底层都是靠打破双亲委派实现的,不是魔法,是精细控制每个类的来源
真正麻烦的从来不是怎么加载一个类,而是怎么让它的依赖、线程上下文、资源查找、GC 行为全部按预期工作——少一个环节,就卡在某个莫名其妙的 NoClassDefFoundError 或内存泄漏上。









