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

Use Gradle goodness to somehow extract and rebuild dependency jars?

这是这个问题的后续:

我在那里选择的答案确实告诉您如何通过规定要排除的依赖项来减少 "fat jar"(即包含其所有依赖项的可执行 jar)的大小。

使用该技术,我将 jar 从 62 MB 减少到 26 MB。但是提取该 jar 并检查组成目录的体积(使用一个名为 TreeSize 的漂亮应用程序)我发现我的 类 仅占 228 KB。剩下的就是依赖。

诚然,我的项目(或其依赖项)确实使用了一些强大的技术:特别是 Lucene (10 MB)、Apache POI (10.5 MB)、openxmlformats (10 MB) 等(当然是预压缩大小) .

事实是,我确信在任何时候实际使用的只是一小部分实际包和包含在这些单独的依赖 jar 中的 类。

考虑到独立的 "fat jar" 不是为多功能性而设计的,所以不需要被它不使用的东西所塞满,并且考虑到 Gradle 非常聪明并且旨在为自动化构建做繁重的工作,可能't/shouldn没有某种方法可以仅提取和打包那些 类 实际需要的:特别是通过分解包装罐,然后仅重新包装类 需要吗?

26 MB 对于一个胖罐子来说并不算大。但是 "technologies" 单个项目使用的越多,它就会变得越大,通过仅使用排除依赖 jar 的粗粒度技术。

PS 我知道这绝非易事!

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

为什么这样的任务不是微不足道的,因为没有人真正知道哪个 类 没有被使用,因为您使用的软件可能使用反射来获取 类(它可能使用某种插件机制,但绑定可能是在运行时完成的)。

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

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

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

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

您可以使用以下方法来严格指定您想要 see/not 在您的 jar 中看到的内容,同时仍然拥有它 运行nable

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 构建将生成 运行nable 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... 经过适当的配置后,您的应用程序将完全满足您的需求,以后无需将其删除。