6

我有一个正在开发的 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 已过时),解决方案要么不起作用要么不好: 我可以在 Android 设备上使用断言吗?

4

2 回答 2

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团队也有同样的误解

于 2016-04-26T22:47:36.193 回答
2

Android Gradle Plugin / Android Studio 4.1 版assert自动在调试构建中启用 Java。

于 2020-10-16T11:09:26.977 回答