android - 向 IntentService 发送消息时产生多个匿名线程
问题描述
我对 Android 开发非常陌生,可能这个问题是如此微不足道,以至于我无法找到关于如何调试或解决问题的明确解释。
在我的应用程序中,我有一个SensorDataListener类,由主要活动实例化并保留对它的引用,并且在onSensorChanged回调(以及一些其他事件)中,在 IntentService 中启动一个名为SensorDataCacheService的作业。现在,虽然这种机制似乎工作正常,但每次将消息添加到 IntentService 的队列时,都会产生 3 到 5 个线程(名为 Thread-1、Thread-2 等),并且永远保持空闲状态,很快就会填满内存,直到应用程序爆炸。
我可以在 Android Studio 内的 Android Profiler 中看到这种情况,但我尝试了一切以找出可能启动它们的原因:因为即使onHandleIntent的内容被完全评论,它们也会产生,我很确定它必须是我做了某种基本错误的设置。
在这里你可以看到: SensorDataListener类
class SensorDataListener(owner: TrainingActivity) : SensorEventListener {
private var context: TrainingActivity = owner
private var settings = PreferenceManager.getDefaultSharedPreferences(context) as SharedPreferences
private var sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
var isRecording = false
companion object {
private val TAG = "SensorDataListener"
}
// SensorEventListener overrides
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
// No need for this at the moment
}
override fun onSensorChanged(event: SensorEvent?) {
if (event != null) {
var intent = Intent(context, SensorDataCacheService::class.java)
intent.putExtra(SENSOR_EVENT_ACCURACY.name, event.accuracy)
intent.putExtra(SENSOR_EVENT_SENSOR_TYPE.name, event.sensor.stringType)
intent.putExtra(SENSOR_EVENT_TIMESTAMP.name, event.timestamp)
intent.putExtra(SENSOR_EVENT_VALUES.name, event.values)
intent.putExtra(MESSAGE_TYPE.name, ADD_TO_CACHE)
context.startService(intent)
}
}
...
}
和SensorDataCacheService
class SensorDataCacheService : IntentService("SensorDataCacheService") {
private lateinit var db: CouchdbClient
companion object {
private const val TAG = "SensorDataCacheService"
private var cache = mutableMapOf<String, MutableList<FeatureData>>()
}
override fun onCreate() {
super.onCreate()
db = CouchdbClient(this)
}
override fun onHandleIntent(intent: Intent?) {
when (intent?.extras?.get(MESSAGE_TYPE.name)) {
ADD_TO_CACHE -> {
cache(intent)
Log.i(TAG, "Add to cache, on ${Thread.currentThread().name}")
}
CLEAR_CACHE -> {
clearCache()
}
}
}
...
}
有趣的是,即使我确定onHandleIntent方法的内容实际上是由 IntentService 的工作线程执行的(我正在从其中打印线程的名称),缓存似乎对于每个调用都不同,所以我不得不它是静态的(kotlin 中的伴随对象)以保持它在所有调用之间共享。
崩溃后 logcat(详细级别)中显示的唯一内容如下:
08-30 20:21:14.587 31786-9669/com.mvettosi.touchlogger A/osi.touchlogge: thread.cc:3888] Unable to create protected region in stack for implicit overflow check. Reason: Out of memory size: 4096
08-30 20:21:15.747 31786-9669/com.mvettosi.touchlogger A/osi.touchlogge: runtime.cc:558] Runtime aborting...
runtime.cc:558] Dumping all threads without appropriate locks held: thread list lock mutator lock
runtime.cc:558] All threads:
runtime.cc:558] DALVIK THREADS (7053):
runtime.cc:558] "osi.touchlogger" prio=10 (not attached)
runtime.cc:558] | sysTid=9669 nice=-10 cgrp=default
runtime.cc:558] | state=R schedstat=( 771357331 2945888 18 ) utm=72 stm=3 core=7 HZ=100
runtime.cc:558] native: #00 pc 00000000003c7324 /system/lib64/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, int, BacktraceMap*, char const*, art::ArtMethod*, void*, bool)+220)
runtime.cc:558] native: #01 pc 00000000004a86c4 /system/lib64/libart.so (art::ThreadList::DumpUnattachedThreads(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, bool)+340)
runtime.cc:558] native: #02 pc 00000000004a7c6c /system/lib64/libart.so (art::ThreadList::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, bool)+460)
runtime.cc:558] native: #03 pc 000000000046a9d0 /system/lib64/libart.so (art::Runtime::Abort(char const*)+392)
runtime.cc:558] native: #04 pc 0000000000008d2c /system/lib64/libbase.so (android::base::LogMessage::~LogMessage()+724)
runtime.cc:558] native: #05 pc 00000000004905b8 /system/lib64/libart.so (art::Thread::ProtectStack(bool)+400)
runtime.cc:558] native: #06 pc 00000000004901cc /system/lib64/libart.so (art::Thread::InstallImplicitProtection()+132)
runtime.cc:558] native: #07 pc 0000000000491bd8 /system/lib64/libart.so (art::Thread::InitStackHwm()+504)
runtime.cc:558] native: #08 pc 000000000048fe40 /system/lib64/libart.so (art::Thread::Init(art::ThreadList*, art::JavaVMExt*, art::JNIEnvExt*)+184)
runtime.cc:558] native: #09 pc 000000000048f400 /system/lib64/libart.so (art::Thread::CreateCallback(void*)+112)
runtime.cc:558] native: #10 pc 0000000000083114 /system/lib64/libc.so (__pthread_start(void*)+36)
runtime.cc:558] native: #11 pc 00000000000233bc /system/lib64/libc.so (__start_thread+68)
runtime.cc:558]
runtime.cc:558] (Aborting thread was not attached to runtime!)
runtime.cc:558] native: #00 pc 00000000003c7324 /system/lib64/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, int, BacktraceMap*, char const*, art::ArtMethod*, void*, bool)+220)
runtime.cc:558] native: #01 pc 000000000046a980 /system/lib64/libart.so (art::Runtime::Abort(char const*)+312)
runtime.cc:558] native: #02 pc 0000000000008d2c /system/lib64/libbase.so (android::base::LogMessage::~LogMessage()+724)
runtime.cc:558] native: #03 pc 00000000004905b8 /system/lib64/libart.so (art::Thread::ProtectStack(bool)+400)
runtime.cc:558] native: #04 pc 00000000004901cc /system/lib64/libart.so (art::Thread::InstallImplicitProtection()+132)
runtime.cc:558] native: #05 pc 0000000000491bd8 /system/lib64/libart.so (art::Thread::InitStackHwm()+504)
runtime.cc:558] native: #06 pc 000000000048fe40 /system/lib64/libart.so (art::Thread::Init(art::ThreadList*, art::JavaVMExt*, art::JNIEnvExt*)+184)
runtime.cc:558] native: #07 pc 000000000048f400 /system/lib64/libart.so (art::Thread::CreateCallback(void*)+112)
runtime.cc:558] native: #08 pc 0000000000083114 /system/lib64/libc.so (__pthread_start(void*)+36)
runtime.cc:558] native: #09 pc 00000000000233bc /system/lib64/libc.so (__start_thread+68)
runtime.cc:558]
08-30 20:21:15.754 31786-9669/com.mvettosi.touchlogger A/libc: Fatal signal 6 (SIGABRT), code -6 (SI_TKILL) in tid 9669 (osi.touchlogger), pid 31786 (osi.touchlogger)
你们中是否有人知道为什么会发生这种情况,或者我可以采用什么方法来弄清楚发生了什么?
提前致谢
解决方案
推荐阅读
- javascript - 在 React Router 中传递数据
- azure-devops - 用户无法在 Azure DevOps 的 sprint 上配置任务板设置
- java - Java中的SOAP消息,WSDL URL替代
- perl - perlcritic 消息:在 void 上下文中使用的映射
- c# - HiQPdf 没有在 pdf 上呈现 Chart.js 图表
- java - 解析多维 JSON 数组错误
- javascript - Next JS 和 Vercel - 开发与生产
- javascript - 使用 lodash 迭代数组和过滤器
- javascript - Selenium JavaScript - 如何在 Jest 测试用例中设置测试 ID
- swift - 如何在小部件 iOS14 中刷新多个计时器?