【问题标题】:Removing unnessary classes from third party libraries and JARs [duplicate]从第三方库和 JAR 中删除不必要的类 [重复]
【发布时间】:2024-01-20 20:51:01
【问题描述】:

我需要从第三方 JAR 中删除未使用的类。为什么要使用工具?

我已经尝试使用ProGuard。但是,它只从项目本身中删除未使用的类,但库 jar - 第三方 - 始终保持不变。

【问题讨论】:

  • 为什么要从 3rd 方 jar 中删除类?
  • 这通常是个坏主意,因为 - 感谢reflection - 没有办法真正知道哪些类未使用,哪些未使用,尤其是在涉及第三方 JAR 时(即你不知道它们在内部是如何工作的)。
  • +Joonas 感谢您的回答。你是对的,但是ProGuard 可以处理反射和内省。那么,有没有其他工具可以对第三方 Jars 做同样的事情?
  • @M.ES:ProGuard 可以处理简单的反射情况,但它的manual 明确警告一般情况:通常不可能预见必须保留哪些类(使用它们的原始名称),因为类名可能是从配置文件中读取的,例如。因此,您必须在 ProGuard 配置中指定它们,使用相同的简单 -keep 选项。
  • 您是否尝试过从库 jar 中提取类并在它们上运行 proguard,就好像它们是主项目的一部分一样?还是 ProGuard 只能删除有源代码的未使用类?

标签: java class jar dependencies proguard


【解决方案1】:

您可以创建一个 uber jar,然后使用 ProGuard。将库类重新打包到 jar 中将是一个挑战,但从您的问题的精神来看,您会更喜欢 uber jar。

正如其他发帖者所评论的那样,您仍然需要小心通过如此多被滥用和误解的反射机制加载的类。

【讨论】:

    【解决方案2】:

    @Joonas Pulakka 是对的。但是,如果您仍然真的想这样做,并确保您的应用程序不会因为ClassNotFoundException 而失败,请使用选项 -verbose:class 运行您的应用程序,执行所有存在的用例,获取包含所有已加载类的日志。然后列出您的第三方库的所有类,并归档您的库中从未加载过的所有类。然后创建仅包含“需要”类的替代 jar 文件并祈祷:)

    祝你好运。

    【讨论】:

    • +AlexR Lool,我说的是 35.7 MB 的 JAR。
    【解决方案3】:

    知道您正在使用哪些类和库是一件好事,即使有移除未使用的东西的风险(正如 Peter 指出的那样),携带任何类型的超重行李都是有成本的,您应该不要只是不断积累。如果您使用反射,那么请掌握您使用它的目的,并系统地摆脱您不需要的东西。您可以更好地理解更精简的代码库有很多好处。

    【讨论】:

      【解决方案4】:

      Java 仅在使用类时加载它们。删除类只会给您带来问题,并且不会在运行时帮助您。 36 MB 的代码并不多,因为只会加载其中的一部分。你有多少内存?如今,大多数 PC 至少有 2000 MB 如果您通过慢速链接下载小程序或 Java WebStart 应用程序,我想您正在使用 pack200(使 jar 更小)并且已经包含了最少的库。

      【讨论】:

      • +Lawrey 感谢您的回答,我理解您的观点。但是,要求是从 JAR 中删除未使用的类,并将所有 JAR 放入单个 FAT JAR。我知道它可能没用,但他们只想让它更干净。
      • 您现在可以将它们全部放入一个 JAR 中。您应该让他们意识到这可能会使应用程序不稳定且无法支持。即,当它打破时,而不是如果,它至少已经警告他们这是一个坏主意。当他们的要求不合理时,您不希望他们责怪您没有做好您的工作。
      • +Lawrey 我会的。谢谢你的建议:)
      • 您可能不知道某些原因,这实际上是非常必要的。我只是想在一个 Android 项目中使用 Goldman Sachs 集合,当我尝试启动我的应用程序时,它会导致 Eclipse 挂起,因为该库是巨大的(例如,包含每个原始类型组合的唯一地图实现)。 ADT 不能挑选它需要的类,因为它将库“索引”为 Dalvik VM 的特殊字节码格式。所以如果我找不到一个工具来摆脱不必要的类,我就不能使用那个库。
      • @PeterLawrey 不,我没有说 Android 的 Dalvik VM 运行时会发生什么。我的意思是,Android Development Toolkit 似乎将项目 libs 文件夹中 jar 中的每个类都转换为 Dalvik VM 的 dex 格式,并且当它试图转换 GS Collections 库时,这个过程似乎是不可行的内存/处理器密集型。我怀疑它不是在库上执行简单的字节码转换,我认为这会占用很少的内存,而是从 jar 中的类中构建一个完整的抽象语法树来执行转换。