【问题标题】:Can I always use the Reflection API if the code is going to be obfuscated?如果代码要被混淆,我可以一直使用反射 API 吗?
【发布时间】:2011-08-07 05:23:02
【问题描述】:

我发现似乎有2个通用的解决方案:

  1. 不要混淆通过反射 API 引用的内容 [Retroguard, Jobfuscate]
  2. 将反射 API 调用中的字符串替换为混淆名称。

这些解决方案仅适用于同一项目中的调用 - 客户端代码(在另一个项目中)可能不会使用反射 API 来访问非公共 API 方法。

在 2 的情况下,它也仅在反射 API 与编译时已知的字符串一起使用时才有效(私有方法测试?)。在这些情况下,dp4j 还提供了一种在混淆后注入反射代码的解决方案。

阅读Proguard FAQ我想知道2是否总是在它说时起作用:

ProGuard 自动处理 像这样的结构 Class.forName("SomeClass") 和 SomeClass.class。被引用的 类被保留在缩小 阶段,字符串参数是 在混淆中正确替换 阶段。

使用可变字符串参数,通常无法确定 它们的可能值。

问:粗体字是什么意思?有什么例子吗?

【问题讨论】:

    标签: java reflection obfuscation proguard


    【解决方案1】:

    对于可变字符串参数,通常无法确定它们的可能值。

    public Class loadIt(String clsName) throws ClassNotFoundException {
        return Class.forName(clsName);
    }
    

    基本上,如果您将非常量字符串传递给 Class.forName,则 proguard 或任何混淆工具通常无法确定您正在谈论的类,因此无法自动为您调整代码。

    【讨论】:

    • 好的,也就是说,String 在编译时是未知的,或者是这种情况的子集(即当编译器无法弄清楚时)。
    • 正确。事实上,上述示例理论上可能意味着通过反射加载的 100 个类。
    【解决方案2】:

    Zelix KlassMaster Java 混淆器可以自动处理所有反射 API 调用。它有一个名为 AutoReflection 的函数,它使用“加密旧名称”到“混淆名称”查找表。

    但是,它再次只能用于同一个混淆项目中的调用。

    http://www.zelix.com/klassmaster/docs/tutorials/autoReflectionTutorial.html

    【讨论】:

      【解决方案3】:

      这意味着:

      String className;
      if (Math.random() <= 0.5) className = "ca.simpatico.Foo";
      else className = "ca.simpatico.Bar";
      Class cl = Class.forName(className);
      

      混淆后不起作用。 ProGuard 没有进行足够深入的数据流分析来查看加载的类名来自这两个字符串文字。

      确实,您唯一可行的选择是决定哪些类、接口和方法应该可以通过反射访问,然后不要混淆它们。您实际上是在为客户端定义一种奇怪的 API - 一种只能以反射方式访问的 API。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-04-04
        • 1970-01-01
        • 1970-01-01
        • 2013-03-24
        • 2018-03-09
        • 1970-01-01
        • 2015-10-08
        • 1970-01-01
        相关资源
        最近更新 更多