Repository navigation
Description
Title: JNI ERROR (app bug): global reference table overflow during high-frequency SSE/streaming with cronet_http
Description:
When using cronet_http (v1.8.0) to establish an SSE (Server-Sent Events) connection or a long-polling loop against a server that pushes data at a very high frequency (e.g., AI text streaming output), the app crashes after keeping the connection alive for a few minutes.
The crash is caused by a JNI global reference table overflow.
Environment
- Package:
cronet_httplatest (1.8.0) - OS: Android
- Flutter: 3.35.6 (Channel stable)
- Dart: 3.9.2
Steps to Reproduce
- Use
cronet_httpto establish an SSE connection (e.g., usinghttp.Requestor streaming client) against an endpoint that pushes high-frequency chunks. - Listen to the response stream and process the data.
- Keep the stream alive for several minutes.
- Observe the JNI crash.
Expected Result
SSE / long-polling connections remain stable indefinitely regardless of callback frequency. Memory and JNI references should be recycled properly.
Actual Result
After sustained high-frequency callbacks, the app crashes with:
JNI ERROR (app bug): global reference table overflow (max=51200)
Crash Stacktrace (Expand)
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
JNI ERROR (app bug): global reference table overflow (max=51200)global reference table dump:
pid: 0, tid: 22938 >>> chat.aimimo.mimo <<<
backtrace:
#00 pc 0x000000000008cc54 /apex/com.android.runtime/lib64/bionic/libc.so (abort+164)
#01 pc 0x00000000008fdfb0 /apex/com.android.art/lib64/libart.so (art::Runtime::Abort(char const*)+1004)
#02 pc 0x000000000001654c /apex/com.android.art/lib64/libbase.so (android::base::SetAborter(std::__1::function<void (char const*)>&&)::$_0::__invoke(char const*)+80)
#03 pc 0x0000000000015a4c /apex/com.android.art/lib64/libbase.so (android::base::LogMessage::~LogMessage()+548)
#04 pc 0x00000000003ed170 /apex/com.android.art/lib64/libart.so (art::JavaVMExt::AddGlobalRef(art::Thread*, art::ObjPtr<art::mirror::Object>)+1528)
#05 pc 0x000000000064ccb4 /apex/com.android.art/lib64/libart.so (art::JNI<false>::NewGlobalRef(_JNIEnv*, _jobject*)+268)
#06 pc 0x000000000000ef9c /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk!libdartjni.so (globalEnv_CallObjectMethod+356) (BuildId: 35ceae377ffd5d09ff92bbe4e9a16c71c89e10f9)
#07 pc 0x000000000046158c /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#08 pc 0x0000000000a351dc /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#09 pc 0x0000000000a3de34 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#10 pc 0x0000000000a3dd4c /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#11 pc 0x00000000009ef2f4 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#12 pc 0x0000000000a347a8 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#13 pc 0x00000000004b1a00 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#14 pc 0x0000000000a341c0 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#15 pc 0x0000000000afd79c /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#16 pc 0x000000000046d654 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#17 pc 0x000000000046d73c /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#18 pc 0x000000000046dc30 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#19 pc 0x000000000046da48 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#20 pc 0x000000000046b01c /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#21 pc 0x000000000046aca0 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#22 pc 0x000000000046ac0c /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#23 pc 0x000000000046e21c /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#24 pc 0x000000000046e2d0 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#25 pc 0x0000000000a69f10 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#26 pc 0x0000000000a6b9a8 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#27 pc 0x000000000046aa5c /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#28 pc 0x000000000046a950 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#29 pc 0x000000000046a914 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#30 pc 0x0000000000463c90 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk (BuildId: dbcf9df9c669f5f412fa88923bec5b37)
#31 pc 0x00000000008b1080 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk!libflutter.so (dart::DartEntry::InvokeFunction(dart::Function const&, dart::Array const&, dart::Array const&)) (BuildId: 131eeda3d8b650ac635d8e496936981e3f591338)
#32 pc 0x00000000009f46e0 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk!libflutter.so (Dart_InvokeClosure) (BuildId: 131eeda3d8b650ac635d8e496936981e3f591338)
#33 pc 0x0000000000814f14 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk!libflutter.so (tonic::DartMicrotaskQueue::RunMicrotasks()) (BuildId: 131eeda3d8b650ac635d8e496936981e3f591338)
#34 pc 0x00000000004a5fd4 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk!libflutter.so (fml::MessageLoopImpl::RunExpiredTasksNow()) (BuildId: 131eeda3d8b650ac635d8e496936981e3f591338)
#35 pc 0x00000000004a9c54 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk!libflutter.so (fml::MessageLoopAndroid::MessageLoopAndroid()::$_0::__invoke(int, int, void*)) (BuildId: 131eeda3d8b650ac635d8e496936981e3f591338)
#36 pc 0x0000000000018224 /system/lib64/libutils.so (android::Looper::pollInner(int)+1060)
#37 pc 0x0000000000017da0 /system/lib64/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+112)
#38 pc 0x00000000000185e4 /system/lib64/libandroid.so (ALooper_pollOnce+100)
#39 pc 0x00000000004a9d64 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk!libflutter.so (fml::MessageLoopAndroid::Run()) (BuildId: 131eeda3d8b650ac635d8e496936981e3f591338)
#40 pc 0x00000000004a7f88 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk!libflutter.so (std::_fl::__function::__func<fml::Thread::Thread(std::_fl::function<void (fml::Thread::ThreadConfig const&)> const&, fml::Thread::ThreadConfig const&)::$_0, std::_fl::allocator<fml::Thread::Thread(std::_fl::function<void (fml::Thread::ThreadConfig const&)> const&, fml::Thread::ThreadConfig const&)::$_0>, void ()>::operator()()) (BuildId: 131eeda3d8b650ac635d8e496936981e3f591338)
#41 pc 0x00000000004a7dc4 /data/app/~~d7Ene3tPHLJpJSL5w7SMeg==/chat.aimimo.mimo-gYA74N_4CWEDE0ozLwFr_w==/split_config.arm64_v8a.apk!libflutter.so (fml::ThreadHandle::ThreadHandle(std::_fl::function<void ()>&&)::$_0::__invoke(void*)) (BuildId: 131eeda3d8b650ac635d8e496936981e3f591338)
#42 pc 0x00000000000fb7cc /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+204)
#43 pc 0x000000000008e490 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64)
Flutter doctor -v
[✓] Flutter (Channel stable, 3.35.6, on macOS 26.3 25D125 darwin-arm64, locale zh-Hans-CN) [467ms] • Flutter version 3.35.6 on channel stable at /Users/embrace/Develop/Flutter/fvm_cache/versions/3.35.6 • Upstream repository https://github.com/flutter/flutter.git • FLUTTER_GIT_URL = https://github.com/flutter/flutter.git • Framework revision 9f455d2486 (5 months ago), 2025-10-08 14:55:31 -0500 • Engine revision d2913632a4 • Dart version 3.9.2 • DevTools version 2.48.0 • Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-lldb-debugging[✓] Android toolchain - develop for Android devices (Android SDK version 36.1.0) [1,391ms]
• Android SDK at /Users/embrace/Library/Android/sdk
• Emulator version 36.2.12.0 (build_id 14214601) (CL:N/A)
• Platform android-36, build-tools 36.1.0
• ANDROID_HOME = /Users/embrace/Library/Android/sdk
• Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
This is the JDK bundled with the latest Android Studio installation on this machine.
To manually set the JDK path, use: flutter config --jdk-dir="path/to/jdk".
• Java version OpenJDK Runtime Environment (build 21.0.9+-14649483-b1163.86)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 26.2) [986ms]
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 17C52
• CocoaPods version 1.16.2
[✓] Chrome - develop for the web [7ms]
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2025.3) [7ms]
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 21.0.9+-14649483-b1163.86)
[✓] VS Code (version 1.109.5) [6ms]
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension can be installed from:
🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[!] Proxy Configuration [6ms]
• HTTP_PROXY is set
! NO_PROXY is not set
[✓] Connected device (2 available) [6.2s]
• macOS (desktop) • macos • darwin-arm64 • macOS 26.3 25D125 darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 145.0.7632.111
! Error: Browsing on the local area network for iPhone133. Ensure the device is unlocked and attached with a cable or associated with the same local area network as this Mac.
The device must be opted into Developer Mode to connect wirelessly. (code -27)
[✓] Network resources [696ms]
• All expected network resources are available.
Hypothesis
It appears to be a classic mismatch between Dart's GC and JNI memory pressure. In high-frequency streaming scenarios (like AI SSE), jnigen or the native binding layer creates JNI Global References for incoming data chunks/callbacks. However, because these objects appear small to Dart, the Dart Garbage Collector doesn't run frequently enough to trigger the NativeFinalizers, causing the JNI Global Reference count to continuously grow until it hits the Android limit (51200) and crashes.
My questions :
- Explicit Release Strategy: Is there any way to manually
.release()or.dispose()the JNI references of the streamed chunks immediately after processing them in Dart, rather than waiting for Dart's GC? (similar to whatjnigenoffers withJObject.release()). - Buffer Reuse: Could
cronet_httpbe optimized internally to use Direct ByteBuffers or reuse existing buffers for streamed responses to avoid generating massive amounts of intermediate JObject references? - Local References Optimization: Ensure that any temporary objects created during the callback handling in the C++ layer are using Local References and are properly deleted (
DeleteLocalRef) before returning to Dart, strictly bounding the number of Global Refs created.
Any guidance or workarounds for high-frequency streaming scenarios would be greatly appreciated!
Activity
brianquinlan commentedon Mar 2, 2026
@goderbauer
To answer your questions:
Streaminterface ofUint8Listdoesn't provide any obvious way of signaling that we are done with theUint8Listcronet_httpuses one directByteBufferper request (seehttp/pkgs/cronet_http/lib/src/cronet_client.dart
Line 227 in 30013eb
cronet_httpcopies part of that buffer into a Uint8List when sending the data to dart (seehttp/pkgs/cronet_http/lib/src/cronet_client.dart
Line 375 in 30013eb
cronet_http1.8 tries to eagerly release as much Java memory as possible.Could you explain how you are using it in a bit more detail? Do you have many clients? Many concurrent requests?
goderbauer commentedon Mar 3, 2026
FYI @liamappelbe
Embrace0611 commentedon Mar 3, 2026
/// SSE Listener with Dio
Future listenStream(
String url, {
Map<String, String>? headers,
Map<String, dynamic>? params,
Map<String, dynamic>? data,
Options? options,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
HttpMethod method = HttpMethod.get,
CancelToken? cancelToken,
required void Function(String data) onEvent,
void Function()? onDone,
void Function(dynamic error)? onError,
}) async {
if (data != null) {
data.removeWhere((key, value) => value == null);
}
headers ??= {};
headers["Accept"] = "text/event-stream";
options ??= Options(
method: methodValues[method],
responseType: ResponseType.stream,
headers: headers,
sendTimeout: const Duration(seconds: 30),
receiveTimeout: const Duration(seconds: 30),
);
}
String _parseSSEEvent(String line) {
if (line.startsWith("data:")) {
final data = line.substring(5);
return data;
} else {
return "";
}
}
void _handleError(dynamic error, void Function(dynamic error)? onError) {
onError?.call(error);
logUtil.e(error.toString());
}
This is the SSE listening logic I implemented using DIO. I'm developing two apps, both of which basically integrate Cronet_http in the same way. This crash occurred in an AI chat application that uses SSE to receive message streams. The other app doesn't have SSE logic, and I haven't seen this crash reported in Google Play either. Therefore, I infer that the crash was caused by SSE.