Android libicuuc.so 中的神秘崩溃 (utext_close)
Android mystery crash in libicuuc.so (utext_close)
我们的 Android 游戏在最近更新后开始在 Google 播放 ANR 和崩溃部分记录奇怪的崩溃。
backtrace:
#00 pc 000000000011be50 /system/lib64/libicuuc.so (utext_close_60+52)
#01 pc 00000000001aa4c4 /system/lib64/libicui18n.so (icu_60::RegexPattern::zap()+212)
#02 pc 00000000001aa560 /system/lib64/libicui18n.so (icu_60::RegexPattern::~RegexPattern()+36)
#03 pc 0000000000094120 /system/framework/arm64/boot-core-libart.oat (offset 0x90000) (java.math.NativeBN.BN_copy [DEDUPED]+160)
#04 pc 000000000018340c /system/framework/arm64/boot-core-libart.oat (offset 0x90000) (libcore.util.NativeAllocationRegistry$CleanerThunk.run+76)
#05 pc 000000000040c754 /system/framework/arm64/boot.oat (offset 0x13b000) (sun.misc.Cleaner.clean+164)
#06 pc 00000000001daa0c /system/framework/arm64/boot.oat (offset 0x13b000) (java.lang.ref.ReferenceQueue.enqueueLocked+236)
#07 pc 00000000001dab2c /system/framework/arm64/boot.oat (offset 0x13b000) (java.lang.ref.ReferenceQueue.enqueuePending+172)
#08 pc 00000000001d7b04 /system/framework/arm64/boot-core-libart.oat (offset 0x90000) (java.lang.Daemons$ReferenceQueueDaemon.runInternal+244)
#09 pc 000000000015978c /system/framework/arm64/boot-core-libart.oat (offset 0x90000) (java.lang.Daemons$Daemon.run+76)
#10 pc 00000000002c1038 /system/framework/arm64/boot.oat (offset 0x13b000) (java.lang.Thread.run+72)
#11 pc 000000000056ef88 /system/lib64/libart.so (art_quick_invoke_stub+584)
#12 pc 00000000000d4204 /system/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+200)
#13 pc 0000000000472fd4 /system/lib64/libart.so (art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char const*)+104)
#14 pc 0000000000474090 /system/lib64/libart.so (art::InvokeVirtualOrInterfaceWithJValues(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, jvalue*)+424)
#15 pc 000000000049f684 /system/lib64/libart.so (art::Thread::CreateCallback(void*)+1120)
#16 pc 0000000000083588 /system/lib64/libc.so (__pthread_start(void*)+36)
#17 pc 00000000000241dc /system/lib64/libc.so (__start_thread+68)
更新中唯一与此相关的更改代码是在我们的分析模块中,我们正在其中进行一些字符串替换:
private static String formatStringForAnalytics(String str) {
if(str == null) {
return "";
}
return str.replaceAll(" ", "_").replaceAll(":", "");
}
我们无法自己重现崩溃。所以我们必须稍等片刻才能制作并发布新的更新,我们禁用这段代码并查看崩溃是否消失。
我只是觉得奇怪,标准字符串替换会导致这样的事情。还有其他人遇到过类似的崩溃吗?
问题实际上是字符串替换函数错误。
API 文档说 replaceAll()
方法
Replaces each substring of this string that matches the given regular
expression with the given replacement.
我更改了代码以使用 replace()
方法
Replaces each substring of this string that matches the literal target
sequence with the specified literal replacement sequence.
这实际上是代码最初打算做的事情。通过此更改,崩溃消失了。
似乎当某些字符串登录到分析时,replaceAll()
设法以某种方式破坏字符串并导致其崩溃。 This answer 关于 replace()
和 replaceAll()
之间差异的问题在这种情况下似乎确实是非常正确的:使用错误的函数会导致细微的错误。
我们的 Android 游戏在最近更新后开始在 Google 播放 ANR 和崩溃部分记录奇怪的崩溃。
backtrace:
#00 pc 000000000011be50 /system/lib64/libicuuc.so (utext_close_60+52)
#01 pc 00000000001aa4c4 /system/lib64/libicui18n.so (icu_60::RegexPattern::zap()+212)
#02 pc 00000000001aa560 /system/lib64/libicui18n.so (icu_60::RegexPattern::~RegexPattern()+36)
#03 pc 0000000000094120 /system/framework/arm64/boot-core-libart.oat (offset 0x90000) (java.math.NativeBN.BN_copy [DEDUPED]+160)
#04 pc 000000000018340c /system/framework/arm64/boot-core-libart.oat (offset 0x90000) (libcore.util.NativeAllocationRegistry$CleanerThunk.run+76)
#05 pc 000000000040c754 /system/framework/arm64/boot.oat (offset 0x13b000) (sun.misc.Cleaner.clean+164)
#06 pc 00000000001daa0c /system/framework/arm64/boot.oat (offset 0x13b000) (java.lang.ref.ReferenceQueue.enqueueLocked+236)
#07 pc 00000000001dab2c /system/framework/arm64/boot.oat (offset 0x13b000) (java.lang.ref.ReferenceQueue.enqueuePending+172)
#08 pc 00000000001d7b04 /system/framework/arm64/boot-core-libart.oat (offset 0x90000) (java.lang.Daemons$ReferenceQueueDaemon.runInternal+244)
#09 pc 000000000015978c /system/framework/arm64/boot-core-libart.oat (offset 0x90000) (java.lang.Daemons$Daemon.run+76)
#10 pc 00000000002c1038 /system/framework/arm64/boot.oat (offset 0x13b000) (java.lang.Thread.run+72)
#11 pc 000000000056ef88 /system/lib64/libart.so (art_quick_invoke_stub+584)
#12 pc 00000000000d4204 /system/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+200)
#13 pc 0000000000472fd4 /system/lib64/libart.so (art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char const*)+104)
#14 pc 0000000000474090 /system/lib64/libart.so (art::InvokeVirtualOrInterfaceWithJValues(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, jvalue*)+424)
#15 pc 000000000049f684 /system/lib64/libart.so (art::Thread::CreateCallback(void*)+1120)
#16 pc 0000000000083588 /system/lib64/libc.so (__pthread_start(void*)+36)
#17 pc 00000000000241dc /system/lib64/libc.so (__start_thread+68)
更新中唯一与此相关的更改代码是在我们的分析模块中,我们正在其中进行一些字符串替换:
private static String formatStringForAnalytics(String str) {
if(str == null) {
return "";
}
return str.replaceAll(" ", "_").replaceAll(":", "");
}
我们无法自己重现崩溃。所以我们必须稍等片刻才能制作并发布新的更新,我们禁用这段代码并查看崩溃是否消失。
我只是觉得奇怪,标准字符串替换会导致这样的事情。还有其他人遇到过类似的崩溃吗?
问题实际上是字符串替换函数错误。
API 文档说 replaceAll()
方法
Replaces each substring of this string that matches the given regular expression with the given replacement.
我更改了代码以使用 replace()
方法
Replaces each substring of this string that matches the literal target sequence with the specified literal replacement sequence.
这实际上是代码最初打算做的事情。通过此更改,崩溃消失了。
似乎当某些字符串登录到分析时,replaceAll()
设法以某种方式破坏字符串并导致其崩溃。 This answer 关于 replace()
和 replaceAll()
之间差异的问题在这种情况下似乎确实是非常正确的:使用错误的函数会导致细微的错误。