Description
Description
Our Spring Boot 3.2.2 application experiences a memory leak leading to an OutOfMemoryError
, with persistent org.eclipse.jetty.server.internal.HttpConnection
objects found in the heap dump. This occurs when using Server-Sent Events (SSE) with Flux endpoints and is particularly evident after an EofException
is thrown by Jetty after the client disconnects but the server attempts to continue emitting events. The issue has been replicated in a minimal project to demonstrate the behavior under specific configurations and versions.
Link to the example project on GitHub
The example application uses Spring Boot 3.2.4 (and Jetty 12.0.7) and has a Flux<ServerSentEvent>
endpoint emitting heartbeats for a duration of 10 seconds.
Steps to Reproduce
- Clone the example project from the provided GitHub repository.
- Start the application using Java 17.0.9 on Spring Boot 3.2.4 with Jetty server 12.0.7.
- Use
curl
to connect to the SSE endpoint atlocalhost:9898/bug/hunt
and then terminate the connection manually using Ctrl+C. - Observe memory usage or take a heap dump to verify if
HttpConnection
instances remain in memory, especially afterEofException
occurs due to attempted heartbeat emissions.
Example
Doing this twice:
$ curl -v localhost:9898/bug/hunt
* processing: localhost:9898/bug/hunt
* Trying [::1]:9898...
* Connected to localhost (::1) port 9898
> GET /bug/hunt HTTP/1.1
> Host: localhost:9898
> User-Agent: curl/8.2.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Fri, 12 Apr 2024 12:21:30 GMT
< Content-Type: text/event-stream
< Transfer-Encoding: chunked
<
event:heartbeat: 0
event:heartbeat: 1
event:heartbeat: 2
^C
Taking a heap dump from the application (using IntelliJ IDEA's memory snapshot) and observing two instances of HttpConnection
:
Expected Behavior
HttpConnection instances should be cleared from memory when the client disconnects, preventing any memory leaks.
Possible Solution
- Downgrading to Jetty version 12.0.3 resolves the issue (works also when using Spring Boot 3.2.0)
- Removing
spring-boot-starter-web
or setting the application toWebApplicationType.REACTIVE
also mitigates the issue
Additional Context
- We have observed the issue with Jetty versions 12.0.4, 12.0.7, and 12.0.8
- We have not been able to reproduce this error outside of Spring Boot, and we are unsure of the underlying problem's source
- Clarification Request: I would appreciate feedback on whether using
spring-boot-starter-web
together with reactive streams (like Flux) for SSE might be inherently problematic. We have simultaneously usedspring-boot-starter-web
andspring-boot-starter-webflux
in our project, utilizingFlux<ServerSentEvent>
endpoints without any issues. However, after upgrading our production environment from Spring Boot 3.0.5 to 3.2.2, we encountered this problem.
Thank you for your attention to this matter. I am more than happy to provide further details or additional information if needed.