使用resource中的jar包资源作为UrlClassloader
本文完全被误导了:
1 ide下可以,打成一个包后不行
2 ide因为有一个解压到target的过程,使被加载的jar包资源确实有一个物理地址,而打成一个包后java启动则没有这个条件
此前的所有尝试,都是使用系统路径,放在本jar包外,本文尝试使用自定义类加载器加载resource中的jar包,https://blog.csdn.net/weixin_33845477/article/details/85970660
该链接只是将resource的jar包读出来传输,而与我要用urlclassloader去加载它是两个概念
这个结构没问题,可以继续用
MyMain
lc3
jars
MySub-1.0.0.jar
MySubBrother-1.0.0.jar
ResourceClassloader
MySub
lc3
ResourceF
MySubBrother
lc3
ResourceG
ResourceH
package lc3;
import java.net.URL;
import java.net.URLClassLoader;
/**
* https://www.cnblogs.com/silyvin/articles/12163982.html
* https://www.cnblogs.com/silyvin/p/12164432.html
* Created by joyce on 2020/1/7.
*/
public class ResourceClassloader {
public static void main(String []f) throws Exception {
URL url1 = ResourceClassloader.class.getResource("jars/MySub-1.0.0.jar");
URL url2 = ResourceClassloader.class.getResource("jars/MySubBrother-1.0.0.jar");
ResourceLoader loader = new ResourceLoader(new URL[]{url1, url2});
test(loader);
test(ResourceLoader.class.getClassLoader());
}
private static void test(ClassLoader classLoader) {
try {
Class c1 = classLoader.loadClass("lc3.ResourceF");
c1.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
try {
Class c1 = classLoader.loadClass("lc3.ResourceG");
// c1.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
try {
Class c1 = classLoader.loadClass("lc3.ResourceH");
c1.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
private static class ResourceLoader extends URLClassLoader {
public ResourceLoader(URL[] urls) {
super(urls);
}
}
}
IDE
ResourceF 加载 G由于没有实例化,导致没有初始化:load/find class 与 forname 在static代码块加载的不同
ResourceH 加载
java.lang.ClassNotFoundException: lc3.ResourceF 模拟母项目加载类——此处证明此法中,类对母加载器不可见,不会影响母项目的依赖jar包冲突,这两个jar包只有这个类加载器可见
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at lc3.ResourceClassloader.test(ResourceClassloader.java:24)
at lc3.ResourceClassloader.main(ResourceClassloader.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
java.lang.ClassNotFoundException: lc3.ResourceG
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at lc3.ResourceClassloader.test(ResourceClassloader.java:31)
at lc3.ResourceClassloader.main(ResourceClassloader.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
java.lang.ClassNotFoundException: lc3.ResourceH
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at lc3.ResourceClassloader.test(ResourceClassloader.java:38)
at lc3.ResourceClassloader.main(ResourceClassloader.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Process finished with exit code 0
PACK:
------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 34.525 s
[INFO] Finished at: 2020-01-11T00:27:21+08:00
[INFO] Final Memory: 47M/502M
[INFO] ------------------------------------------------------------------------
JoycedeMacBook:MyMain joyce$ java -jar target/MyMain-1.0.0-jar-with-dependencies.jar
java.lang.ClassNotFoundException: lc3.ResourceF
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at lc3.ResourceClassloader.test(ResourceClassloader.java:24)
at lc3.ResourceClassloader.main(ResourceClassloader.java:18)
java.lang.ClassNotFoundException: lc3.ResourceG
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at lc3.ResourceClassloader.test(ResourceClassloader.java:31)
at lc3.ResourceClassloader.main(ResourceClassloader.java:18)
java.lang.ClassNotFoundException: lc3.ResourceH
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at lc3.ResourceClassloader.test(ResourceClassloader.java:38)
at lc3.ResourceClassloader.main(ResourceClassloader.java:18)
java.lang.ClassNotFoundException: lc3.ResourceF
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at lc3.ResourceClassloader.test(ResourceClassloader.java:24)
at lc3.ResourceClassloader.main(ResourceClassloader.java:19)
java.lang.ClassNotFoundException: lc3.ResourceG
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at lc3.ResourceClassloader.test(ResourceClassloader.java:31)
at lc3.ResourceClassloader.main(ResourceClassloader.java:19)
java.lang.ClassNotFoundException: lc3.ResourceH
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at lc3.ResourceClassloader.test(ResourceClassloader.java:38)
at lc3.ResourceClassloader.main(ResourceClassloader.java:19)
--------------------------------
下面那些与本文主体无关,保留
对于反射调用,可以用此法,对于不想反射调用,可以maven依赖同样的包,使用SystemPath或在编译期使用jar plugin但不copy出lib,这样既能通过编译及开发,又能不增加打包后的大小,其大小==assembly插件
运行期由于这些包没有打入classpath,而没有被系统类加载器加载,当我们自定义类加载器加载时,就不会因为双亲委派而被这些jar包截胡,A.class.getClassloader必然是自定义类加载器不会是系统类加载器
ps一个奇怪的地方,src下的资源文件没有被maven打包入target,导致class.getResource返回null
https://www.liangzl.com/get-article-detail-7827.html 人家好好的
https://blog.csdn.net/qq_32706349/article/details/81067650 这老兄碰到了同样的问题
https://blog.csdn.net/wqksy/article/details/88937868 解决方案
<build>
<!--https://www.cnblogs.com/silyvin/articles/12163982.html-->
<!--https://www.cnblogs.com/silyvin/p/12164432.html-->
<resources>
<resource>
<directory>${basedir}/src/main/java</directory>
<includes>
<include>**/*.jar</include>
</includes>
</resource>
</resources>
关于resource maven知识,更多的看:maven build resource
1.14留言,尼玛,这个代码直接把resource下的资源文件也忽略了,改为:
<build>
<!--https://www.cnblogs.com/silyvin/articles/12163982.html-->
<!--https://www.cnblogs.com/silyvin/p/12164432.html-->
<resources>
<resource>
<directory>${basedir}/src/main/java</directory>
<includes>
<include>**/*.jar</include>
</includes>
</resource>
<resource>
<directory>${basedir}/src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
</resource>
</resources>
</resources>
浙公网安备 33010602011771号