-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
Describe the bug
The SignalR Java client version 9.0.4 has a memory leak when using the stream()
method for real-time data streaming. The issue is caused by the use of unbounded ReplaySubject.create()
in two places:
InvocationRequest.java:14
-private final Subject<Object> pendingCall = ReplaySubject.create();
HubConnection.java:796
-ReplaySubject<T> subject = ReplaySubject.create();
(in thestream()
method)
These unbounded replay subjects cache ALL emitted items indefinitely, causing memory to grow without bounds during long-running WebSocket connections with continuous data streams.
To Reproduce
Steps to reproduce the behavior:
- Create a SignalR Java client connection
- Use the
stream()
method to subscribe to a high-frequency data stream (e.g., real-time trading data) - Keep the connection running for extended periods (>1 hour)
- Monitor memory usage - it will continuously grow until OutOfMemoryError occurs
Example code:
HubConnection hubConnection = HubConnectionBuilder.create("wss://example.com/hub")
.withAccessTokenProvider(Single.just(accessToken))
.build();
hubConnection.start().blockingAwait();
// This will cause memory leak over time
Observable<MarketData> stream = hubConnection.stream(MarketData.class, "StreamMarketData", "symbol");
stream.subscribe(data -> {
// Process real-time data
});
Expected behavior
The streaming connection should maintain stable memory usage over time, not accumulating all historical data in memory.
Actual behavior
Memory usage grows continuously as ReplaySubject
caches all emitted items. This leads to OutOfMemoryError after extended periods of streaming.
Workaround
Currently, we're forced to periodically disconnect and reconnect the SignalR connection every 5-15 minutes to clear the internal buffers and prevent OOM errors.
Suggested Fix
Replace unbounded ReplaySubject.create()
with either:
- Bounded replay:
ReplaySubject.createWithSize(bufferSize)
- PublishSubject for no caching:
PublishSubject.create()
- Make buffer size configurable
Environment
- SignalR Java Client version: 9.0.4
- Java version: 11/17
- Platform: Android
- RxJava version: 3.x
Stack trace
java.lang.OutOfMemoryError: Failed to allocate a 24 byte allocation with 1349584 free bytes and 1317KB until OOM
at com.android.org.conscrypt.ConscryptEngine.newResult(ConscryptEngine.java:1363)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:933)
...
at okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.kt:0)
at okhttp3.internal.ws.RealWebSocket.loopReader(RealWebSocket.kt:293)
Additional context
This issue affects production applications using SignalR for real-time data streaming, particularly in financial trading applications where data streams are continuous and high-frequency.
Expected Behavior
No response
Steps To Reproduce
No response
Exceptions (if any)
No response
.NET Version
No response
Anything else?
No response