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

posted on 2020-01-07 22:04  silyvin  阅读(718)  评论(0编辑  收藏  举报