简体   繁体   English

Android Paho Mqtt - close() 与 unregisterResources() - OutOfMemoryError

[英]Android Paho Mqtt - close() v.s. unregisterResources() - OutOfMemoryError

Whenever I encounter an error in the paho MQTT client, I attempt a reconnect 60 seconds later:每当我在 paho MQTT 客户端中遇到错误时,我都会在 60 秒后尝试重新连接:

override fun connectionLost(cause: Throwable) {
    LOG.e("Connection Lost :: $cause")
    cleanupClient()
    retry { connect() }
}

private fun cleanupClient(){
    try {
        for (i in topicList.indices) {
            client!!.unsubscribe(topicList[i])
        }
        client!!.close()
        client = null
    } catch (e: Exception) {
        LOG.e("Could not clean up!", e)
    }
}

fun retry(cb: () -> Unit){
    handler.removeCallbacksAndMessages(null)
    handler.postDelayed({
        cb()
    }, 60000)
}

So if the app is sitting without internet, it will continuously attempt to reconnect until it finally does.因此,如果应用程序没有互联网,它会不断尝试重新连接,直到最终成功。 The issue is that after a few hundred attempts (a couple hours), the app crashed with an Out of Memory Issue:问题是,经过几百次尝试(几个小时)后,该应用程序因内存不足问题而崩溃:

java.lang.OutOfMemoryError: OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack available

I only have 2 class-global variables, my handler and my MqttAndroidClient:我只有 2 个类全局变量,我的处理程序和我的 MqttAndroidClient:

private var client: MqttAndroidClient? = null

// For retries
val handler = Handler()

And of those, only the client is ever re-assigned a value.其中,只有客户端会被重新分配一个值。 My understanding is that in the clean up function, because I close and null out the client, the JVM should clean up my resources.我的理解是,在清理功能中,因为我关闭并清空了客户端,JVM 应该清理我的资源。 The documentation for client.close(): client.close() 的文档:

Close the client.关闭客户端。 Releases all resource associated with the client .释放与客户端关联的所有资源 After the client has been closed it cannot be reused.客户端关闭后无法再使用。 For instance attempts to connect will fail.例如,尝试连接将失败。

There is also another function called unregisterResources()还有另一个函数叫做 unregisterResources()

Unregister receiver which receives intent from MqttService avoids IntentReceiver leaks.取消注册从 MqttService 接收意图的接收器可避免 IntentReceiver 泄漏。

It seems to me that only client.close() needs to be called, but I'm unsure if this will cause other issues.在我看来,只需要调用 client.close(),但我不确定这是否会导致其他问题。

And if there is anything else that you would suggest that I look at, I would love your advice!如果您还建议我查看其他任何内容,我会喜欢您的建议!

Somewhere internally in the client, there is a memory leak.在客户端内部的某个地方,存在内存泄漏。 So re-creating the client each time there is an issue will eventually cause your app to crash, regardless of if you use close.因此,每次出现问题时重新创建客户端最终都会导致您的应用程序崩溃,无论您是否使用 close。

When I built the app this way, I went off of this answer on SO( Java Eclipse Paho Implementation - Auto reconnect ).当我以这种方式构建应用程序时,我在 SO( Java Eclipse Paho Implementation - Auto reconnect )上放弃了这个答案。 As @hardillb pointing out, this is now outdated.正如@hardillb 指出的,这已经过时了。 Instead, use the reconnect callback:相反,使用重新连接回调:

conOpt.isAutomaticReconnect = true

implement MqttCallbackExtended on your class:在您的类上实现 MqttCallbackExtended:

class NotificationService : Service(), MqttCallbackExtended {

And then implement connectComplete() override fun connectComplete(unusedArg1: Boolean, unusedArg2: String?) {然后实现connectComplete()覆盖fun connectComplete(unusedArg1:Boolean,unusedArg2:String?){

LOG.i("Connection completed!")
        try{
            subscribe()
        } catch(e: java.lang.Exception){
            LOG.e("Unable to re-subscribe", e)
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM