为了账号安全,请及时绑定邮箱和手机立即绑定

maven-shade-plugin的作用是什么?为什么要重定位Java包?

/ 猿问

maven-shade-plugin的作用是什么?为什么要重定位Java包?

饮歌长啸 2019-10-23 14:22:49

我发现有人的pom.xml中使用了maven-shade-plugin。我以前从未使用过maven-shade-plugin(并且我是Maven n00b),所以我试图了解使用它的原因及其作用。


我看了看Maven文档,但是我听不懂这句话:


“该插件提供了将工件打包在uber-jar中的功能,包括其依赖项,并且可以对某些依赖项的包进行着色(即重命名)。” 该页面上的文档似乎不太适合新手。


什么是“超级罐子”?为什么有人要做一个?重命名依赖包的意义何在?我尝试浏览了Maven-shade-plugin apache页面上的示例,例如“为Uber Jar选择内容”,但是我仍然不明白使用“ shading”可以完成什么。


任何指向说明性示例/用例的指示(带有在这种情况下为什么需要阴影的解释-它要解决什么问题)将不胜感激。最后,什么时候应该使用maven-shade-plugin?


查看完整描述

3 回答

?
莫回无

简而言之,Uber JAR是包含所有内容的JAR。

通常在Maven中,我们依赖于依赖项管理。工件仅包含其自身的类/资源。Maven将负责根据项目的构建时间来找出项目的所有工件(JAR等)。

uber-jar是一种具有所有依赖关系的东西,可以提取依赖关系的内容,并将其与项目本身的类/资源放在一个大的JAR中。通过具有这样的uber-jar,它很容易执行,因为您只需要一个大JAR即可运行大量应用,而无需大量小JAR。在某些情况下,这也简化了分配。

只是一个旁注。避免将uber-jar用作Maven依赖项,因为它破坏了Maven的依赖项解析功能。通常,我们仅为最终工件创建uber-jar以便进行实际部署或手动分发,而不是将其放入Maven存储库。


更新:我刚刚发现我还没有回答问题的一部分:“重命名依赖包有什么意义?”。这是一些简短的更新,希望对有类似问题的人们有所帮助。

创建uber-jar以便于部署是shade插件的一个用例。还有其他一些涉及包重命名的常见用例。

例如,我正在开发Foo库,这取决于库的特定版本(例如1.0)Bar。假设我无法使用其他版本的Barlib(因为API更改或其他技术问题等)。如果我在Maven中简单地声明Bar:1.0Foo的依赖项,就有可能陷入一个问题:一个Qux项目依赖于Foo,并且也依赖于Bar:2.0(并且它不能使用,Bar:1.0因为Qux需要使用中的新功能Bar:2.0)。这是一个难题:应该Qux使用Bar:1.0(哪个Qux代码不起作用)还是Bar:2.0(哪个Foo代码不起作用)?

为了解决此问题,的开发人员Foo可以选择使用shade插件重命名其用法Bar,以便将Bar:1.0jar中的所有类都嵌入Foojar中,并将嵌入Bar类的包从更改com.barcom.foo.bar。这样,Qux可以放心地依赖,Bar:2.0因为现在Foo不再依赖Bar,它使用的是Bar位于另一个包中的“更改”的自己的副本。


查看完整回答
反对 回复 2019-10-23
?
幕布斯6054654

我最近在想自己为什么elasticsearch会遮蔽并重新定位一些(但不是全部)依赖项。这是项目维护者@kimchy的解释:


阴影部分是有意的,我们在Elasticsearch中使用的阴影库是针对Elasticsearch的所有意图和目的部分,所使用的版本与Elasticsearch公开的内容以及基于库工作原理的内部库使用方式紧密相关(以及版本之间的差异),netty和番石榴就是很好的例子。


顺便说一句,我实际上提供了几罐elasticsearch,其中一个带有未着色的lucene,另一个带有已着色的lucene,我没有问题。虽然不确定如何用Maven做到这一点。我不想提供一个不会掩盖netty / jackson的版本,例如,elasticsearch对它们有很深的使用习惯(例如,对netty的任何先前版本使用即将推出的缓冲改进功能,但当前版本除外)实际使用的内存要多于使用较少的内存)。


- https://github.com/elasticsearch/elasticsearch/issues/2091#issuecomment-7156766


还有一个来自drewr的信息:


阴影对于使我们的依赖关系(尤其是netty,lucene,番石榴)与我们的代码保持接近非常重要,这样即使上游提供程序落后,我们也可以解决问题。我们可能会分发代码的模块化版本,这将有助于解决您的特定问题(例如,#2091),但是目前我们不能简单地删除阴影的依赖项。您可以构建自己的ES本地版本,直到找到更好的解决方案为止。


- https://github.com/elasticsearch/elasticsearch/pull/3244#issuecomment-20125452


因此,这是一个用例。作为说明性示例,下面是如何在elasticsearch的pom.xml(v0.90.5)中使用maven-shade-plugin。这些artifactSet::include行指示它要放入uber JAR中的依赖项(基本上,在生成目标Elasticsearch jar时,将它们解压缩并与Elasticsearch自己的类一起重新打包。(如果您还不知道,则JAR文件是只是一个ZIP文件,其中包含程序的类,资源等,以及一些元数据。您可以提取其中一个文件来查看其组合方式。)


这些relocations::relocation行是相似的,除了在每种情况下它们还将指定的替换应用于依赖项的类-在这种情况下,将它们置于之下org.elasticsearch.common。


最后,本filters节从目标JAR中排除了一些不应包含在其中的东西-例如JAR元数据,蚂蚁构建文件,文本文件等,它们打包在一起并具有某些依赖项,但不属于超级JAR。


<plugins>

    <plugin>

        <groupId>org.apache.maven.plugins</groupId>

        <artifactId>maven-shade-plugin</artifactId>

        <version>2.1</version>

        <executions>

            <execution>

                <phase>package</phase>

                <goals>

                    <goal>shade</goal>

                </goals>

            </execution>

        </executions>

        <configuration>

            <minimizeJar>true</minimizeJar>

            <artifactSet>

                <includes>

                    <include>com.google.guava:guava</include>

                    <include>net.sf.trove4j:trove4j</include>

                    <include>org.mvel:mvel2</include>

                    <include>com.fasterxml.jackson.core:jackson-core</include>

                    <include>com.fasterxml.jackson.dataformat:jackson-dataformat-smile</include>

                    <include>com.fasterxml.jackson.dataformat:jackson-dataformat-yaml</include>

                    <include>joda-time:joda-time</include>

                    <include>io.netty:netty</include>

                    <include>com.ning:compress-lzf</include>

                </includes>

            </artifactSet>

            <relocations>

                <relocation>

                    <pattern>com.google.common</pattern>

                    <shadedPattern>org.elasticsearch.common</shadedPattern>

                </relocation>

                <relocation>

                    <pattern>gnu.trove</pattern>

                    <shadedPattern>org.elasticsearch.common.trove</shadedPattern>

                </relocation>

                <relocation>

                    <pattern>jsr166y</pattern>

                    <shadedPattern>org.elasticsearch.common.util.concurrent.jsr166y</shadedPattern>

                </relocation>

                <relocation>

                    <pattern>jsr166e</pattern>

                    <shadedPattern>org.elasticsearch.common.util.concurrent.jsr166e</shadedPattern>

                </relocation>

                <relocation>

                    <pattern>org.mvel2</pattern>

                    <shadedPattern>org.elasticsearch.common.mvel2</shadedPattern>

                </relocation>

                <relocation>

                    <pattern>com.fasterxml.jackson</pattern>

                    <shadedPattern>org.elasticsearch.common.jackson</shadedPattern>

                </relocation>

                <relocation>

                    <pattern>org.joda</pattern>

                    <shadedPattern>org.elasticsearch.common.joda</shadedPattern>

                </relocation>

                <relocation>

                    <pattern>org.jboss.netty</pattern>

                    <shadedPattern>org.elasticsearch.common.netty</shadedPattern>

                </relocation>

                <relocation>

                    <pattern>com.ning.compress</pattern>

                    <shadedPattern>org.elasticsearch.common.compress</shadedPattern>

                </relocation>

            </relocations>

            <filters>

                <filter>

                    <artifact>*:*</artifact>

                    <excludes>

                        <exclude>META-INF/license/**</exclude>

                        <exclude>META-INF/*</exclude>

                        <exclude>META-INF/maven/**</exclude>

                        <exclude>LICENSE</exclude>

                        <exclude>NOTICE</exclude>

                        <exclude>/*.txt</exclude>

                        <exclude>build.properties</exclude>

                    </excludes>

                </filter>

            </filters>

        </configuration>

    </plugin>

</plugins>


查看完整回答
反对 回复 2019-10-23
?
噜噜哒

小警告

尽管这并不能说明为什么要使用Maven-shade-plugin(因为所选答案描述得很好),但我想指出我对此有问题。它更改了JAR(因为它在做什么),并且导致了我的软件的回归。


因此,我没有使用此(或maven-jarjar-plugin),而是使用了JarJar的二进制文件,该文件似乎可以正常工作。


我在这里发布我的解决方案,因为我花了一些时间找到一个不错的解决方案。


Downlaod JarJar的JAR文件

您可以从以下位置下载jar:https: //code.google.com/p/jarjar/ 在左侧菜单中,您有一个下载链接。


如何使用JarJar以便将JAR的类从一个包重定位到另一个包

在此示例中,我们将包从“ com.fasterxml.jackson”更改为“ io.kuku.dependencies.com.fasterxml.jackson”。-源JAR被称为“ jackson-databind-2.6.4.jar”,新的修改的(目标)JAR被称为“ kuku-jackson-databind-2.6.4.jar”。-“ jarjar” JAR文件的版本为1.4


创建一个“ rules.txt”文件。文件内容应为(注意“ @”字符前的句点):规则com.fasterxml.jackson。** io.kuku.dependencies.com.fasterxml.jackson。@ 1


运行以下命令:java -jar jarjar-1.4.jar处理rules.txt jackson-databind-2.6.4.jar kuku-jackson-databind-2.6.4.jar


将修改后的JAR安装到本地存储库

在这种情况下,我将安装位于“ c:\ my-jars \”文件夹中的3个文件。


mvn install:安装文件-Dfile = C:\ my-jars \ kuku-jackson-annotations-2.6.4.jar -DgroupId = io.kuku.dependencies -DartifactId = kuku-jackson-annotations -Dversion = 2.6.4- Dpackaging = jar


mvn install:安装文件-Dfile = C:\ my-jars \ kuku-jackson-core-2.6.4.jar -DgroupId = io.kuku.dependencies -DartifactId = kuku-jackson-core -Dversion = 2.6.4- Dpackaging = jar


mvn install:安装文件-Dfile = C:\ my-jars \ kuku-jackson-databind-2.6.4.jar -DgroupId = io.kuku.dependencies -DartifactId = kuku-jackson-annotations -Dversion = 2.6.4- Dpackaging = jar


在项目的pom中使用修改后的JAR

在此示例中,这是项目pom中的“ dependencies”元素:


<dependencies>

    <!-- ================================================== -->

    <!-- kuku JARs -->

    <!-- ================================================== -->

    <dependency>

        <groupId>io.kuku.dependencies</groupId>

        <artifactId>kuku-jackson-annotations</artifactId>

        <version>2.6.4</version>

    </dependency>

    <dependency>

        <groupId>io.kuku.dependencies</groupId>

        <artifactId>kuku-jackson-core</artifactId>

        <version>2.6.4</version>

    </dependency>

    <dependency>

        <groupId>io.kuku.dependencies</groupId>

        <artifactId>kuku-jackson-databind</artifactId>

        <version>2.6.4</version>

    </dependency>

</dependencies>


查看完整回答
反对 回复 2019-10-23

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信