使用Gradle善于以某种方式提取和重建依赖性jar?

时间:2017-02-21 19:15:25

标签: java gradle dependencies executable-jar

以下是这个问题:Gradle, Tika - Exclude some dependency packages making a "fat jar" too fat

我在那里选择的答案确实告诉你如何通过规定要排除哪些依赖项来减少“胖罐”(即包含其中所有依赖项的可执行jar)的大小。

使用这种技术我将罐子从62 MB减少到26 MB。但是,提取该jar并检查组成目录的卷(使用名为TreeSize的漂亮应用程序),我发现我的类只占228 KB。其余的是依赖。

不可否认,我的项目(或其依赖项)确实使用了一些强大的技术:特别是Lucene(10 MB),Apache POI(10.5 MB),openxmlformats(10 MB)等(当然,预压缩大小)。 / p>

问题是,我确信在任何时候,实际上只使用这些个体相关罐中包含的实际包和类的一小部分。

鉴于一个独立的“胖罐”并非设计用于多功能性,因此不需要使用它不使用的东西,并且鉴于Gradle非常聪明并且设计用于繁重的工作自动化构建,可能不会/不应该只有一些方法来提取和打包实际需要的那些类:特别是通过爆炸包装罐然后只重新打包所需的类?

对于胖罐来说,26 MB不是一个巨大的尺寸。但是,单个项目使用的“技术”越多,通过仅使用排除依赖性罐子的粗粒度技术就会变得越大。

PS我知道这将是一项远非琐碎的工作!

2 个答案:

答案 0 :(得分:3)

您可以使用以下方法严格指定您想要在罐子里看到/看不到的内容,同时让它可以运行

apply plugin: 'java'

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependecies {
your dependencies
}   

jar {
    archiveName = 'Name.jar'

    manifest {
        attributes 'Main-Class': 'uk.co.cdl.Main',
                'Class-Path': configurations.runtime.files.collect { "lib/$it.name" }.join(' '),
                'Implementation-Version': project.version
    }

    from(configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }) {
        exclude 'what you want to get rid dependencies/directories/files' etc
    }
}

通过扩展jar任务的这个解决方案,你的gradle构建将产生可运行的jar,其中包含运行所需的编译配置中的库。

PS。如果您从依赖项中获取了大量传递依赖项,请尝试使用

将其排除
compile (artifactGrp:artifactId:version) {transitive=false}

PS2。我相信有一个netflix插件可以扫描您的gradle脚本,检查未使用的依赖项 https://github.com/nebula-plugins/gradle-lint-plugin

PS3。有一个插件可以扫描使用的依赖项的漏洞等 https://jeremylong.github.io/DependencyCheck/dependency-check-gradle/

编辑:

您的问题可能是您在依赖关系时没有使用正确的配置值得检查哪些依赖项compile compileOnly以及runtimetest等。或provided...经过适当的配置后,您的应用程序将完全符合您的需求,以后不需要将其删除。

答案 1 :(得分:1)

可能有一个Gradle插件可以对已使用和未使用的类进行某种分析,但Gradle本身并没有这样的功能。它只是收集您根据需要声明的依赖项,并添加传递的依赖项。 ShadowJar插件只需解压缩并将它们打包到一个罐子里。

为什么这样的任务不重要是因为没有人能够真正知道哪些类没有被使用,因为你使用的软件可能会使用反射来获取类(它可能使用某种插件机制,但很可能绑定是在运行时)。

要手动执行此操作,you can filter the contents of the shadowJar

shadowJar {
   exclude 'classes-you-dont-want.class'
}

未经测试,但该插件看起来足够强大,可能会允许您执行以下操作:

shadowJar {
   exclude '**/*bad.class'
}