what is causing this extra heap usage...
Take a look at this line:
BufferedReader bufferedReader = req.getReader();
Note that you are not actually creating a new BufferedReader. When you call getBufferedReader
, Jetty creates a BufferedReader which wraps an InputStreamReader which wraps a custom InputStream implementation which wraps a byte buffer. I am pretty sure that by executing the code which reads the entire message, you create large byte buffer inside the request object which stores the entire contents of the message body. Plus the request object maintains a reference to the readers.
At the beginning of the function you called:
Continuation cc = ContinuationSupport.getContinuation(req);
I believe your continuation is holding onto the request which is storing all the data. So the simple act of reading the data is allocating the memory which will be preserved until you discontinue
your continuation.
One thing you might try just as an experiment. Change your code to:
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(req.getInputStream()));
This way Jetty won't allocate it's own readers. Again - I don't know how much data is really stored in the readers compared to the rest of the request object - but it might help a little.
[update]
Another alternative is to avoid the problem. That's what I did (although I was using servlet 3.0 rather than Continuations). I had a resource - let's call it /transfer
which would POST some data, then use an AsyncContext
to wait for a response. I changed it to two requests with different URLS - /push
and /pull
. Any time I had some content that needed to be sent from client to server, it would go in the /push
request which would then immediately return without creating an AsyncContext
. Thus, any storage in the request is freed up right away. Then to wait for the response, I sent a second GET request with no message body. Sure - the request hangs around for a while - but who cares - it does not have any content.
You may have to rethink your problem and determine if you can perform your task in pieces - multiple requests - or whether you really have to handle everything in a single request.