提问人:Mohammad 提问时间:2/3/2023 更新时间:2/4/2023 访问量:186
在代码中存储(部分)Proguard 混淆映射
Storing (partial) Proguard obfuscation mapping in code
问:
在这样的 android Java 代码中:
String methodName = "myMethod"
public void myMethod() {
}
是否可以在运行时找出方法的混淆名称?
我知道我可以要求 Proguard 不要混淆该方法,但我正在寻找一种方法来避免这种情况,并且仍然能够通过反射使用它。
我找不到 Proguard 配置,但我想知道是否可以有一个 gradle 任务来合并生成的映射?
答:
1赞
Oleg
2/3/2023
#1
代码混淆通常只是将类和变量重命名为简短和随机的文本,同时保持适当的依赖关系。无法获取函数的混淆名称,因为它是随机生成的,并且每次运行总是不同的。
以下是一些选项:
相反,如果要保持函数不可读,请从混淆中排除该类,并使用随机文本命名函数。
-keep 类 <com.package.DontObfuscate>
在第一次混淆后,保留文件并在
mapping.txt
proguard-rules.pro
-应用映射映射:.txt
这将防止为类/变量生成新名称。
-applymapping
- 指定重用在 ProGuard 的上一次模糊处理运行中打印出来的给定名称映射。映射文件中列出的类和类成员将接收与其一起指定的名称。未提及的类和类成员将获得新名称。
- 寻找一种不在代码中使用类/接口扩展的反射的方法。
评论
0赞
Mohammad
2/3/2023
谢谢。我认为这个选项最接近我想做的事情applymapping
2赞
Holger
2/4/2023
#2
如果需要方法内部的方法名称,可以使用
String methodName;
public void myMethod() {
methodName = new Object() {}.getClass().getEnclosingMethod().getName();
}
或者,在较新的 Java 版本中
String methodName;
public void myMethod() {
methodName = StackWalker.getInstance(Set.of(), 1)
.walk(s -> s.map(StackWalker.StackFrame::getMethodName).findFirst())
.orElseThrow();
}
当您需要外部名称时,即调用它时,您可以使用注释标记方法并搜索它。
@Retention(RetentionPolicy.RUNTIME) @interface Marker {}
@Marker
public void myMethod() {
}
String name = Arrays.stream(ContainingClass.class.getDeclaredMethods())
.filter(m -> m.isAnnotationPresent(Marker.class))
.map(Method::getName)
.findFirst().orElseThrow();
正如其他人所说,不使用 Reflection 可能是更好的选择。例如,引用使用匹配功能接口的方法,不是反射访问:
Runnable method = this::myMethod;
public void myMethod() {
}
这将在混淆后继续工作。
评论
0赞
Mohammad
2/6/2023
感谢您的建议。可悲的是,就我而言,我正在处理许多类和方法,因此我试图避免为每个类和方法单独添加标识注释。但似乎没有一种自动化的方法。
评论