sofastack / sofa-ark

SOFAArk is a light-weight,java based classloader isolation framework.
https://www.sofastack.tech/projects/sofa-boot/sofa-ark-readme/
Apache License 2.0
1.57k stars 500 forks source link

URLClassLoader加载fatJar里的jar 和 普通的jar 行为不一致的地方 #248

Closed johnyannj closed 5 years ago

johnyannj commented 5 years ago

URLClassloader 加载一个普通jar包的的url,获取一个特殊路径的resource,会返回null 举例:

URLClassLoader loader= new URLClassLoader(new URL[] {
                new URL("file:/D:/a.jar")
        }, null);
loader.getResource("C:\\a.yaml") ;//返回null的。

在对fatJar支持以后, 使用URLClassloader加载嵌套jar包的url 然后getResource("C:\a.yaml"), 会报错, 举例:

URLClassLoader loader= new URLClassLoader(new URL[] {
                new URL("jar:file:/D:/a.jar!/libs/b.jar!/")
        }, null);
loader.getResource("C:\\a.yaml") ;

下面是一个使用spring boot里的fatjar的支持的例子, sofa-ark的代码和spring-boot类似,应该现象是一致的:

    public static void main(String[] args) throws IOException {

        org.springframework.boot.loader.jar.JarFile.registerUrlProtocolHandler();

        JarFileArchive jarFileArchive = new JarFileArchive(new File("d:\\a.jar"));

        List<Archive> nestedArchives = jarFileArchive.getNestedArchives(
                entry -> entry.getName().startsWith("libs/") && !entry.isDirectory());

        List<URL> urlList = new LinkedList<>();
        for (Archive nestedArchive : nestedArchives) {
            urlList.add(nestedArchive.getUrl());
        }
        URLClassLoader urlClassLoader = new URLClassLoader(urlList.toArray(new URL[0]));

        urlClassLoader.getResource("C:\\a.yaml");
    }
Exception in thread "main" java.lang.IllegalArgumentException: name
    at sun.misc.URLClassPath$Loader.findResource(URLClassPath.java:693)
    at sun.misc.URLClassPath.findResource(URLClassPath.java:215)
    at java.net.URLClassLoader$2.run(URLClassLoader.java:569)
    at java.net.URLClassLoader$2.run(URLClassLoader.java:567)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findResource(URLClassLoader.java:566)
    at java.lang.ClassLoader.getResource(ClassLoader.java:1096)

我搜了下,overflow上面也有人遇到过 https://stackoverflow.com/questions/51203893/java-lang-illegalargumentexception-name

看代码已经进入sun的包了,很难调试,没再跟踪。

或者,是否可以考虑在下面这个位置把这个异常抓一下(或许又是馊主意)? com.alipay.sofa.ark.container.service.classloader.AbstractClasspathClassLoader#getLocalResource

QilongZhang commented 5 years ago

可以尝试调试下,sun 相关的代码可以谷歌 download。fatjar 处理是spring boot 定义的特殊加载资源的方法,用法可能和普通的资源加载不一样,这个问题目前看来和 Ark 没什么关联,没有抓异常的必要。

johnyannj commented 5 years ago

有影响的场景:

有些开源软件,它为了兼容classpath和system file path。 习惯做法是会先getResource,看classpath下面有没有,如果没有,再当文件路径处理。

这种情况会报错。

QilongZhang commented 5 years ago

有影响的场景:

有些开源软件,它为了兼容classpath和system file path。 习惯做法是会先getResource,看classpath下面有没有,如果没有,再当文件路径处理。

这种情况会报错。

麻烦尽量提供你提到的开源软件的复现 demo 哈

QilongZhang commented 5 years ago

我先关闭这个 issue,如果有需求请重新代开。