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

7

我有一台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(即过时)的解决方案要么不起作用,要么不好: 我能在Android设备上使用assert吗?

1
我必须对你的前提提出一些异议,即断言在生产中不会增加任何风险。如果一个断言失败了,你已经注定要失败了;只是问题在于如何失败。 - Louis Wasserman
1
@LouisWasserman 如果一个断言在生产环境中会失败(如果运行),那么你就有问题了,但是不清楚这个问题有多大。考虑到它们不会运行,而且在现有的潜在错误上添加断言并不会增加额外的风险。 - Travis Well
2个回答

4

自Android Gradle插件/自Android Studio 4.1版本起,会自动启用在调试构建中使用Java assert


但是警告:在Android中从不启用断言。请改用BuildConfig.DEBUG条件检查。 - Andrew Glukhoff

3
我不情愿地提交答案似乎是:你无法在ART上启用断言。有效的方法是将所有断言替换为显式抛出的AssertionError,包装在if语句中,如下所示:
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
不确定为什么他们对断言如此漠不关心。这里有一些过去的错误报告链接,记录了他们的冷漠,但没有给出原因。 - 就我而言,我已经采取了使用源代码预处理器的方法。 - Michael Allan
当前的Android Studio(4.2 Canary 11)建议使用if (BuildConfig.DEBUG && !(condition)) { error("Assertion failed") }代替assert(condition),因为Assertions are never enabled in Android. Use BuildConfig.DEBUG conditional checks insteaderror()函数会抛出一个带有给定消息的IllegalStateException异常。(这全部是针对Kotlin的,但Java应该类似并且也建议这样做。) - xuiqzy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接