【发布时间】:2014-11-17 04:22:53
【问题描述】:
Proguard 很好地删除了琐碎的日志调用。 (使用 assumenosideeffects 关键字)
但它处理非平凡日志调用很差。
我所说的“非平凡”指的不仅仅是一个字符串。
例如:Log.i(TAG,"velocity="+velocity)"。
Proguard 保留new StringBuilder("velocity="),以及附加的变量来保留值,并没有太多地掩盖该变量。它仅删除对 Log 的最终调用。
字符串将保留在那里,浪费内存、cpu 周期并帮助破解者理解代码。
所以为了解决这个问题,我用if(BuildConfig.DEBUG){...} 包装了我的应用程序中的每个非平凡 调试日志调用。
但是用if(..){..} 包装每个日志很乏味且容易出错。
它肯定不是 DRY(不要重复自己)。
有没有办法标记 Proguard(或任何其他方式)完全删除的方法,包括所有调用方法?
类似:
@proguard_purge
public static void vanishingDebug(String whatever) {
Log.i(TAG,whatever);
}
所以该方法会被混淆器消失,并且所有对该方法的调用也会递归消失?
详细说明
混淆将优化代码并删除未使用或排除的方法。
但是代码编译会在方法调用之前生成额外的字节码之前,这些字节码将被删除,并且即使在混淆之后,前面的代码将保留下来,并留下如下代码:
new StringBuilder("velocity=").append(a)
(假设在编译时无法确定a。要测试,请使用velocity=Math.random();)
这使得混淆代码很容易理解。
要重现此问题,您需要安装 dex2jar 将 apk 转换为 jar,并安装 JAD 将 jar 转换为 java 代码。
您会看到真正留下的东西,并感到恐惧。
示例
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("TAG", "Simple Comment"); // << Disappears well!
double index = Math.random();
index++;
Log.i("TAG2", "log_index=" + index); // << hmm... (!)
// class with only log calls inside
new ReferencedClass();
// simple method call
MyLogger.notLog("no_log" + index); // << stays, as expected
// simple method call with only Log call inside (aka "Log Wrapper")
MyLogger.log("log" + index); // << stays, as expected
Log.i("TAG2", "This is random:" + Math.random()); // << stays, same as above
setContentView(R.layout.activity_main);
}
使用这个混淆配置:
-assumenosideeffects class android.util.Log {
public static *** isLoggable(java.lang.String, int);
public static *** d(...);
public static *** v(...);
public static *** i(...);
public static *** w(...);
public static *** e(...);
}
它将被混淆为可以反编译和反混淆的状态:
protected void onCreate(Bundle paramBundle)
{
super.onCreate(paramBundle);
double d = 1.0D + Math.random();
new StringBuilder("log_index=").append(d).toString();
new b();
a.a("no_log" + d);
new StringBuilder("log").append(d).toString();
a.a();
new StringBuilder("This is random:").append(Math.random()).toString();
setContentView(2130903064);
}
【问题讨论】:
-
你用过assumenosideeffects关键字吗?
-
@NickT 当然,这就是我使用 trivial 的意思,我编辑了我的问题以澄清这一点。