【问题标题】:Creating compact jar without dependencies创建没有依赖关系的紧凑 jar
【发布时间】:2016-07-06 13:21:01
【问题描述】:

给定一个常规的 java gradle 项目,我们有一些在 jar 清单中定义的入口 main 方法,以及一堆依赖项。

现在通常当我们创建一个发行版时,我们可能会使用应用程序插件并具有类似这样的结构作为输出

/bin  (some splatform specific scripts that point to our jar)
/lib  (our jar + all dependencies with their dependencies etc...)

问题是,即使我们只使用了直接依赖项中的几个类,它们和所有传递依赖项最终都会在分发中。例如,从 100M 的分布中,只有 1M 实际上是可以运行的代码,并且可能与我们的应用程序有任何关系......

像 proguard 这样的工具可以通过各种优化缩小特定 jar 中的代码,但它不会关心代码是否未使用。未使用的意思是 main 方法是 jar 的入口点,根据 main 中的代码,它可能永远不会使用实际应用程序 jar 中的大部分代码以及库 jar 中的更多代码......

我们的目标是创建这个仅包含实际将使用的代码的 1M jar,同时考虑到 jar 清单中的主要方法是什么...

我已经搜索了很多但找不到任何解决方案,proguard 非常接近,但我找不到任何方法让它只关心代码的特定流程而不是所有代码。

是否有任何工具可以做到这一点?

【问题讨论】:

  • 附注:请记住,有 a) 反射...很难确定哪些类是真正需要的...然后 b)停机问题转化为:对于任意程序和输入,您可以确定是否曾经使用过某个函数(又名类)。所以,我要说的是:也许对你的问题有务实的答案,但大理论对你不利。
  • @Jägermeister 通常如果一个库依赖于反射,你会弄清楚并明确告诉proguard不要删除这个或那个类......在我的情况下,我根本不使用它......关于b ) 那个怎么样?如果proguard已经这样做了,它会通过字节码,如果它检测到死代码,它将摆脱它,或者任何未使用的类......所以proguard做我想要的它只是它不关心入口点......
  • stackoverflow how-to-find-unused-dead-code-in-java-projects 的可能副本,它关心源代码。问题是关于编译的代码。无论如何,答案可能会有所帮助。
  • 绝对不是重复,这是关于使用特定于应用程序的 main 方法进行收缩,而不仅仅是消除死代码...
  • 我想我会让问题更具体到proguard,因为据我所知,我唯一的选择是如果我可以让它摆脱特定代码流未使用的任何东西......

标签: java optimization gradle proguard


【解决方案1】:

您对 ProGuard 所做的事情的描述是错误的:

像 proguard 这样的工具可以用各种不同的方式压缩特定 jar 中的代码 优化,但它不会关心代码是否未使用。通过未使用的 i 意味着 main 方法是 jar 的入口点,取决于 main 中的代码可能永远不会使用 实际的应用程序 jar 以及库 jar 中的更多内容......

您所描述的 unused code 正是 ProGuard 在其 收缩 步骤中所做的。从种子开始(在您的情况下为 main 方法),它将查找正在使用的任何类/方法并删除其他所有内容。

如果保留了太多类,很可能是由于某些-keep 规则。您必须根据需要调整它们。例如,如果第 3 方库不使用反射,则不需要保留。

ProGuard 还可以在其优化步骤中删除dead code:方法内的任何根据流分析永远不会执行的指令都将被删除。这种技术在指令级上运行,而收缩在类级上运行。

【讨论】:

  • 但我不知道在哪里可以给它我的主要方法?这就是我所做的
  • injars "$buildDir/libs/${project.name}.jar", injars configurations.compile.all, outjars 'build/libs/proguard-gradle-example.out.jar'跨度>
  • 我希望它获取包括依赖项在内的所有 jars,并且只给出一个 jar...我在哪里告诉 proguard 这个特定的 X.Jar 是我的实际应用程序?
  • 我查看了github.com/loopj/proguard-gradle-example/blob/master/… 以获取示例,但我没有看到如何指定 proguard 需要开始的确切 jar...
  • 你必须指定你的入口点,例如您要保留的主要方法:-keep class xxx.yyy.YourApplication { void main(...); }
猜你喜欢
  • 1970-01-01
  • 2019-04-05
  • 2021-11-01
  • 1970-01-01
  • 2016-02-22
  • 2012-07-04
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
相关资源
最近更新 更多