Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Maven shade在所有模块中的重新定位?_Maven_Bukkit - Fatal编程技术网

Maven shade在所有模块中的重新定位?

Maven shade在所有模块中的重新定位?,maven,bukkit,Maven,Bukkit,我有一个maven多模块项目,它有一个父pom项目和一堆模块。其中一个模块是“主模块”,它将所有库着色到其中。所有其他模块都依赖于该模块并使用提供的库 主模块是一个Bukkit插件,它将其他模块作为扩展加载。这些扩展都使用自己的类加载器加载,但是加载的类在加载器之间共享,以便能够相互依赖。他们还可以依赖其他Bukkit插件,因为他们的父类加载器是Bukkit的PluginClassLoader,它还可以在插件之间共享加载的类以允许交互 问题就从这里开始:不同的插件可能使用同一个库,但该库的类可能

我有一个maven多模块项目,它有一个父pom项目和一堆模块。其中一个模块是“主模块”,它将所有库着色到其中。所有其他模块都依赖于该模块并使用提供的库

主模块是一个Bukkit插件,它将其他模块作为扩展加载。这些扩展都使用自己的类加载器加载,但是加载的类在加载器之间共享,以便能够相互依赖。他们还可以依赖其他Bukkit插件,因为他们的父类加载器是Bukkit的PluginClassLoader,它还可以在插件之间共享加载的类以允许交互

问题就从这里开始:不同的插件可能使用同一个库,但该库的类可能被不同的类加载器加载,从而导致LinkageErrors和其他问题

我解决这个问题的想法是通过maven shade插件重新定位主模块中的库。这与仅由主模块使用的库一样有效。但是,重新定位其他模块使用的库会导致运行时ClassNotFoundExceptions,因为这些模块仍然搜索正常的包名,而不是重新定位的包名。 然后我尝试将导入更改为重新定位的包,但我的IDE(IntelliJ)找不到类


有人知道如何解决这个搬迁问题吗?或者在类加载问题上可能有不同的方法?

我的问题几乎与您的问题完全相同(从这个问题的年龄判断)。虽然我没有一个更干净的解决方案覆盖其他插件版本的库,但我确实有一个解决IntelliJ不识别重新定位的类的方法

为了防止它抱怨,我将着色jar(带有重定位)作为IntelliJ库添加到目标模块中。 您可以这样做:

  • 转到
    文件>项目结构…>模块>(目标模块)>依赖项
  • 使用
    Add(green+)>1选择着色罐子。JAR或目录…
  • 您现在应该可以在libaries列表中看到带阴影的jar
  • 虽然乍一看似乎是可行的,但此解决方案解决方案有几个注意事项:

    • 通过Maven的模块依赖关系,代码仍然可以看到未重新定位的类,如果您碰巧使用了它们,则只有在使用Maven编译时才能看到。(您可以删除模块依赖项,但每次重新导入pom时都会读取该依赖项)
    • 如果在jar文件名中包含版本号,则每次更改项目版本时都必须更新jar路径(解决方法:指定静态
      project.build.finalName
    • 添加新方法或更改签名时,需要再次编译库模块。(这可以通过为着色依赖项创建单独的模块来解决,这实际上也可以解决文件名问题)

    5年后,在一个非常相似的环境中(Bukkit->SpongeApi),我再次遇到了这个问题,但这次我找到了(可能是唯一令人满意的)解决方案:

  • 主模块将其着色版本作为主工件,因此依赖项只能看到重新定位的类,并且不知道原始类名。在我们的例子中,这没有什么区别,因为主模块无论如何都是一个提供的依赖项,但它也防止使用者意外地直接使用重新定位的类。IntelliJ不关心重新定位,因此它不知道新重新定位的类。将着色版本附加为次要工件(shadedArtifactAttached选项设置为true)使依赖项对依赖项再次可见

  • 依赖模块必须应用与主模块相同的重新定位规则,因此插件会将类名更正为运行时可用的类名


  • 这样IntelliJ就不知道重新定位,但也不需要知道。如有必要,可以在父pom中配置重新定位,以确保所有项目的规则一致。

    我已经有一段时间没有尝试过这样做了。到目前为止,该项目已经进行了重大重组。我的问题中提到的主模块现在是一个单独的maven项目,其余的模块分为3个不同的项目(主模块、附加模块、原型模块)和一个单独的共享父模块,没有任何依赖项声明。因此,模块从核心依赖项而不是父依赖项继承它们的依赖项。我认为现在应该可以搬迁了。我仍然喜欢你提到的IntelliJ解决方案