spring - 类加载器问题

标签 spring jar classloader gradle

关于类加载器的行为,我有一个有趣的问题。

问题一:类加载器加载jar的顺序是什么?

给出了以下jar和包含类:

a.jar
  +-com/scheffield/foo/A.class

b.jar
  +-com/scheffield/foo/B.class

将加载哪个类?

问题二:类路径中文件的路径和名称是唯一的吗?

给出了以下jar和包含类(真实示例):
spring-beans-3.0.3.RELEASE.jar
  +-META-INF/spring.schemas

spring-aop-3.0.3.RELEASE.jar
  +-META-INF/spring.schemas

我可以告诉您的是,这两个文件都是由Spring加载的,否则会发生异常(请参阅this article)。

我为什么要问:

我做了一个所谓的大 jar (cookbook entry for gradle)。多数民众赞成在一个jar与应用程序类和所有其他依赖项解压缩并打包在大jar中。而且我不确定如何处理重复的文件。

最佳答案

  • 类已解决,但是类加载器想要解决它们(这就是拥有类加载器体系结构的全部要点)。实际上,您处理的大多数类加载器都是java.net.URLClassLoader的变体,它根据目录和jar的搜索路径(类路径)加载类(和资源)。搜索路径中的每个位置都被视为类的来源,并且按顺序搜索位置。
  • 不,名称不是唯一的。将使用搜索顺序中遇到的第一个。

  • 如果将 jar 组合成一个大 jar ,则肯定有发生冲突的可能性。如果您小心地将它们从有效类路径中的最后一个源合并到第一个(因此将后面的jar和早期的jar覆盖),您将获得大致相同的结果。

    我之所以这么说,是因为jars中的 list 包含其他需要合并的处理指令。例如, list 可以包含Class-Path attribute,它在类路径中包含其他jar。可以合并jar,但丢失 list 属性,这些 list 属性指定了实际必要的类路径的一部分。如果 list 中包含sealedsigned jar ,那么在不违反 jar 签名部分的情况下,您可能根本无法进行合并。

    总而言之, jar 并不是真正设计为以这种方式合并的。它可以工作,但是有很多错误的可能性,其中一些是不可能解决的。常见的错误原因是合并两个jar文件,并最终导致多个文件具有相同的路径,而zip文件中允许使用相同的路径。 ant jar和zip任务使您可以合并多个源,并且可能产生此类问题。

    实际上,最好将包含许多jar和源的Web应用程序 bundle 到一个WAR或EAR归档文件中。这就是它们存在的全部意义。

    关于spring - 类加载器问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4437028/

    相关文章:

    spring - Spring Boot中如何手动向Redis添加数据并获取缓存数据?

    java - 类加载器并加载位置不等于其包的类

    java - Maven:在运行时使用测试 jar 时缺少依赖项

    java - Android中parcelable.readArrayList()中ClassLoader的使用

    java - Bootstrap Classloader加载的类

    java - HQL 在 executeUpdate 上生成不完整的 'cross join'

    java - 文件上传zuul代理请求大小问题

    java - Maven 插件中无法识别 aspectj

    java - 添加索引到 jar 文件,引用外部 jar 文件

    java - 无法通过 Web 服务以编程方式运行 jar 文件