Memory leak in `ArrayRetainableByteBufferPool$RetainedBucket`
KGOH opened this issue · comments
Jetty version(s)
11.0.17
Java version/vendor
openjdk version "21.0.3" 2024-04-16 LTS
OpenJDK Runtime Environment Temurin-21.0.3+9 (build 21.0.3+9-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.3+9 (build 21.0.3+9-LTS, mixed mode, sharing)
OS type/version
Inside of a eclipse-temurin:21-alpine
docker container
Description
On several (not all) different instances of my application that are using the same functionality I observe a constantly growing direct memory usage
(the saw-tooth pattern is due to manual application restarts)
I created a heap dump using jmap -dump:format=b,file=heap.hprof $PID
.
I inspected it with VisualVM and Eclipse MAT and both point to org.eclipse.jetty.io.ArrayRetainableByteBufferPool$RetainedBucket
Here are screenshots from VisualVM and Eclipse MAT from the dump inspection:
How to reproduce?
🤷
Memory leaks are notoriously hard to track down, and sometimes hard to differentiate from normal (but large) memory consumption. In your MAT screenshot, I can see that the retained bucket has almost 1.3 million buffer entries in it, so I'm fairly positive that there is indeed some form of leak somewhere.
Unfortunately, almost everything in Jetty works with buffers so just knowing that something, somewhere is not always releasing them isn't nearly enough information to stand a chance to track down the bug. We are going to need your help here to narrow down the areas that may contain the leaky code.
The key to identify what's causing the leak is to find some correlation between certain request types and the growth of memory usage, then try to reproduce the leak with a much narrowed down sample app.
Here's a list of places to start looking for correlations:
- Are you using HTTP2 or HTTP1 only? Are you performing upgrades from H1 to H2?
- Are you using websockets?
- Are you using SSL?
- Have you configured Jetty to perform GZIP compression?
- Are you using the Jetty client (maybe via the proxy servlet)?
In the meantime, you can try limiting the maximum size of the memory retained by the buffer pool by configuring the maxBucketSize
, maxHeapMemory
and maxDirectMemory
of the ArrayByteBufferPool
. This could affect performance, but should limit the maximum memory Jetty uses for its buffers.
Finally, another thing worth mentioning: Jetty 12 is much more robust in the face of buffer leaks, as in between other improvements, it contains some code to detect and repair them most of the time so you may want to give it a shot if you can.
Hello, sorry for silence. I've been investigating another memory leak which has been occuring in caddy which proxies my jetty server. I've replaced caddy with nginx and the memory consumption rate has changed significantly. I'll continue observation for another couple of weeks.
If you have any idea how caddy could cause the memory leak in jetty, let me know
In the meanwhile here's the thread in the caddy repo's issue
caddyserver/caddy#6322 (comment)
![image](https://private-user-images.githubusercontent.com/11963737/355789450-293e54b9-8787-4c26-80f3-fd49b5509b69.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjM2ODY4ODEsIm5iZiI6MTcyMzY4NjU4MSwicGF0aCI6Ii8xMTk2MzczNy8zNTU3ODk0NTAtMjkzZTU0YjktODc4Ny00YzI2LTgwZjMtZmQ0OWI1NTA5YjY5LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTUlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE1VDAxNDk0MVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTVmNzYwMWMwYWQ0Y2YxMzgxZDMwMjBkNDVhMDA1ZGVhMjZmZDEwZTRkZWU3ZDc5NjU2OGNlNDQ4ZjNkMGRmYjImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.3ftSUw2EgDkLHbj4HUqm_nwt_n8AEZQYO_umNvis8R4)
![image](https://private-user-images.githubusercontent.com/11963737/355791882-74c82d3d-4e98-44a3-b891-15b62c6d6601.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjM2ODY4ODEsIm5iZiI6MTcyMzY4NjU4MSwicGF0aCI6Ii8xMTk2MzczNy8zNTU3OTE4ODItNzRjODJkM2QtNGU5OC00NGEzLWI4OTEtMTViNjJjNmQ2NjAxLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTUlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE1VDAxNDk0MVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWNhYzU5YWY4YjBlZWQ5OTMxM2YxY2E1YzRlZmYzMTJmMWQxZDliMWY0ZDg2YzBkZjY4NmM4MTZiODc2ZjU1YTYmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.e10U28e0AH03ThLzPv1uKyhnz73tx1XyC11kTDFtyq4)
Caddy must be doing something slightly differently from nginx that's triggering the leak in Jetty, but it's hard to be more precise than that.
Something else that may help: we have backported the leak-tracking connection pool from Jetty 12, and it's going to land in the soon-to-be-released Jetty 11.0.23. Once that release is out, you may want to try configuring the leak tracking connection pool, wait until you can confirm the memory consumption goes to an abnormal level then take a heap dump.
The tracking pool should then contain some fairly precise information about the root cause of the leak that should help us track it down.