如何在Android Runtime(ART)上启用语言级断言?

时间:2016-03-14 20:44:02

标签: java android testing assertions android-runtime

我正在开发一个Pixel-C。我的最低API级别是21,这也是ART取代Dalvik的级别。我试过了两个:

adb shell setprop dalvik.vm.enableassertions all
adb shell setprop debug.assert 1

他们似乎成功执行了。我已经放了

assert false : "assertions are active!";

在我的onStart中,我没有在logcat中看到任何堆栈跟踪。我希望应用程序在安装并运行后立即退出。请告诉我如何让这个断言执行。

请不要提及JUnit或其他做断言的方法,也不要提出任何需要明确抛出错误的解决方案。生产代码不应该抛出错误,也不应该尝试捕获和处理它们。这就是为什么断言被添加到语言中的原因,以便在测试环境中违反不变量时导致应用崩溃,而不会产生任何开销或生产中的任何风险。

这个6岁的问题基本相同,但对于Dalvik(IE已过时)而且解决方案要么不起作用要么不好: Can I use assert on Android devices?

2 个答案:

答案 0 :(得分:2)

我不情愿地提出答案似乎是:你不能在ART上启用断言。有效的是用if语句中包含的显式抛出的AssertionError替换所有断言,如下所示:

if (BuildConfig.DEBUG) {
  if (writeBuffer.hasRemaining()) {
    // As with all assertions, this condition should never be met.
    throw new AssertionError("whole buffer not written");
  }
}

显然,在API级别21,22和23中,ART实际上会在安装时从非调试版本中完全删除此if块的字节码,即BuildConfig.DEBUG == false。在这些API级别,ART在安装时将字节码编译为本机,但是对于Android N而言正在改变。所以我推断,在Android N上,ART可能仍然会在检查BuildConfig.DEBUG的生产中看到可忽略的性能损失,直到优化器可能编译它为止在一定量的使用发生后退出。

我不喜欢这个,因为它删除了选择为apk中的特定包运行断言的功能。现在的选择是整个构建的粒度,并且仅在构建时。

这很糟糕的另一个主要原因是它冗长而丑陋。断言的简洁性使它们适合于内联记录代码。尽管这些被黑客攻击的断言可以作为文档,但它们不再是不起眼和易读的。看那个例子。这应该是一行,而不是五行。

如果您知道为什么ART似乎不支持断言,例如,有关技术障碍或Google内部政治的内幕知识,请发表评论或留下新的答案。我的假设是,对断言的有用性和作用的广泛误解,以及反模式使用的普遍性导致Android团队只是禁用该功能而不是教育每个人。也许Android团队遭受同样的misunderstandings

答案 1 :(得分:1)

Android Gradle插件/从4.1版开始,Android assert s会自动在调试版本中启用。