使用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>