Closed jiangyunpeng closed 5 years ago
@jiangyunpeng 感谢反馈. 确认在执行 Class.getResource("/")
返回 NULL. 本质是 BizClassLoader 和 PluginClassLoader 在处理 getResource("")
返回结果和 ClassLoader.getResource("")
不一致. 如果方便,能否 PR 解决下,感谢。
另外BizClassLoader和PluginClassLoader的getResourcesInternal是否存在问题? 如果plugin中声明了export resource,是否应该优先使用plugin的,做一下去重。
protected Enumeration<URL> getResourcesInternal(String name) throws IOException {
List<Enumeration<URL>> enumerationList = new ArrayList<>();
// 1. find exported resources
enumerationList.add(getExportResources(name));
// 2. find local resources
enumerationList.add(getLocalResources(name));
return new CompoundEnumeration<>(
enumerationList.toArray((Enumeration<URL>[]) new Enumeration<?>[0]));
}
@jiangyunpeng 应该是没有问题,Plugin导出的资源是希望其他 Plugin 和 Biz 能加载到的。
是否应该优先使用plugin的,做一下去重。
去重的意义在哪?有时就是希望获取所有同名资源
假设biz被动依赖了一个0.8的dubbo,同时biz也显示依赖了一个1.0的dubbo-plugin,通过export "com.alibaba.dubbo.*"可以让jvm忽略掉0.8的dubbo只加载1.0中的dubbo classes,但是resource现在同时load 了biz和plugin两份资源就会有冲突, 把resource也当成class同等对待就好理解了。
@jiangyunpeng resource 是比较特殊的存在,诸如 dubbo 和 sofa-rpc 提供很多扩展机制。有些扩展提供了默认的扩展,放在SPI文件中,但是允许应用自定义覆盖。这个时候如果按你说的去重,那么用户定义的文件就无效了。
不会吧,用户定义的资源的jar路径和dubbo官方不一样,我说的去重是针对同一个jar不同版本中的resource。
@jiangyunpeng 通过getResources 的加载资源,再根据路径判断版本号去重,并不是很好的方式,你可以使用getResource替代,如果你仅仅想加载plugin导出的资源。 通过最后url的路径格式解析版本是一个很hack的方式,也不准。
getResource()的调用不是我能控制的,是各种库在用,比如spring 加载META-INF/spring.factories 就是getResources()。
@jiangyunpeng 你引入多个spring 版本,getResources(), 也是不会做去重的。getResources() 是为了获取classpath所有的指定路径的资源,框架内部尝试做去重不认为是合适的。另外正如上一条回复,也没法有一个很好的去重策略,从承担的风险和解决的问题来看,不值得这么做。 或许你可以给出遇到的具体问题。 上面你提到的多版本dubbo资源只是现象,可以具体说下因为此遇到的具体问题。
Describe the bug
在sofa-ark 运行中,
会出现NPE。
原因在Class的实现中/会被解析成空字符串:
AbstractClasspathClassloader. getResource 在方法开头做了检测,当为空字符串直接返回null导致NPE.
Steps to reproduce
测试代码
输出:
Minimal yet complete reproducer code (or GitHub URL to code)
Environment
java -version
):uname -a
):