接收大量 FCM 消息导致内存泄漏
Memory leak from recieving lots of FCM messages
我们目前正在开发一个使用 Pusher Beams 的 kotlin 应用程序。它运行得非常好,直到每秒收到一定数量的通知(4+)。然后通常会因以下两个例外之一而失败:
Fatal Exception: java.lang.OutOfMemoryError: Could not allocate JNI Env
at java.lang.Thread.nativeCreate(Thread.java)
at java.lang.Thread.start(Thread.java:730)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:941)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1359)
at okhttp3.ConnectionPool.put(ConnectionPool.java:153)
或
Fatal Exception: android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed.
at android.database.CursorWindow.<init>(CursorWindow.java:108)
at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:198)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:138)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:132)
由于这两个异常似乎都拒绝分配更多内存,因此我们使用 Profiler 分析了该应用程序。那里的消费看起来很稳定,直到崩溃。还添加了 LeakCanary,它不报告任何(已知)泄漏......
只有 MessagingService 的实例和 okhttp 的连接似乎存在/打开的时间比必要的时间更长。
这是我的服务片段:
class NotificationService : MessagingService() {
...
override fun onMessageReceived(remoteMessage: RemoteMessage) {
val data = remoteMessage.data
if(data.containsKey("action")){
val action = data["action"].toString()
if(action == "ticketUpdate"){
val json = Json(JsonConfiguration.Stable)
val tickets: List<Ticket> = json.parse(Ticket.serializer().list, data["tickets"].toString())
val ticketIterator = tickets.iterator()
ticketIterator.forEach { ticket ->
ticketHelper.updateTicket(ticket)
}
}
}
}
}
- 我们是否错误地处理传入消息?
- 如何继续调试这个问题?
- 我在 throughput of fcm messages 上没有发现任何关于此的限制。推动器部分是否存在任何已知问题?
虽然花了点时间,但解决了我的问题:
https://github.com/pusher/push-notifications-android/pull/106
我们目前正在开发一个使用 Pusher Beams 的 kotlin 应用程序。它运行得非常好,直到每秒收到一定数量的通知(4+)。然后通常会因以下两个例外之一而失败:
Fatal Exception: java.lang.OutOfMemoryError: Could not allocate JNI Env
at java.lang.Thread.nativeCreate(Thread.java)
at java.lang.Thread.start(Thread.java:730)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:941)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1359)
at okhttp3.ConnectionPool.put(ConnectionPool.java:153)
或
Fatal Exception: android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed.
at android.database.CursorWindow.<init>(CursorWindow.java:108)
at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:198)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:138)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:132)
由于这两个异常似乎都拒绝分配更多内存,因此我们使用 Profiler 分析了该应用程序。那里的消费看起来很稳定,直到崩溃。还添加了 LeakCanary,它不报告任何(已知)泄漏...... 只有 MessagingService 的实例和 okhttp 的连接似乎存在/打开的时间比必要的时间更长。
这是我的服务片段:
class NotificationService : MessagingService() {
...
override fun onMessageReceived(remoteMessage: RemoteMessage) {
val data = remoteMessage.data
if(data.containsKey("action")){
val action = data["action"].toString()
if(action == "ticketUpdate"){
val json = Json(JsonConfiguration.Stable)
val tickets: List<Ticket> = json.parse(Ticket.serializer().list, data["tickets"].toString())
val ticketIterator = tickets.iterator()
ticketIterator.forEach { ticket ->
ticketHelper.updateTicket(ticket)
}
}
}
}
}
- 我们是否错误地处理传入消息?
- 如何继续调试这个问题?
- 我在 throughput of fcm messages 上没有发现任何关于此的限制。推动器部分是否存在任何已知问题?
虽然花了点时间,但解决了我的问题:
https://github.com/pusher/push-notifications-android/pull/106