При отправке сообщения в IntentService создаются несколько анонимных потоков. - PullRequest
0 голосов
/ 30 августа 2018

Я очень новичок в разработке Android, и, возможно, этот вопрос настолько тривиален, что я не смог найти четкого объяснения того, как даже отладить или подойти к проблеме.

В моем приложении есть класс SensorDataListener , созданный основным действием и сохраняющий ссылку на него, и в onSensorChanged обратный вызов (и при некоторых других событиях) запускает задание в IntentService с именем SensorDataCacheService . Теперь, хотя этот механизм работает должным образом, каждый раз, когда сообщение добавляется в очередь IntentService, от 3 до 5 потоков (с именами Thread-1, Thread-2 и т. Д.) Создаются и остаются бездействующими навсегда, быстро заполняя памяти, пока приложение не взорвется.

Я вижу, что это происходит в Android Profiler внутри Android Studio, но я попробовал все, чтобы выяснить, что может их запустить: так как они порождаются, даже если 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)

Кто-нибудь из вас имеет представление о том, почему это происходит, или какой подход я мог бы использовать, чтобы выяснить, что происходит?

Заранее спасибо

...