[#JERSEY-2677] Leak for RequestScoped injectables if

advertisement
[JERSEY-2677] Leak for RequestScoped injectables if async server model is
used Created: 06/Oct/14 Updated: 10/Sep/15 Resolved: 19/Feb/15
Status:
Project:
Component/s:
Affects
Version/s:
Fix Version/s:
Closed
jersey
core, performance
2.12, 2.13
Type:
Reporter:
Resolution:
Labels:
Remaining
Estimate:
Time Spent:
Original
Estimate:
Bug
bodewig
Fixed
hk2, memory-leak
Not Specified
2.17
Priority:
Assignee:
Votes:
Critical
Adam Lindenthal
0
Not Specified
Not Specified
Description
The dispose method of a HK2 factory bound to RequestScoped is never called when the
async server model is used. I intend to attach a simple unit test using grizzly but we see the
same result using Jetty as runtime.
It seems that the RequestScoped.Instance reference count is not decremented often enough to
trigger disposal in the async case as we managed to work around the problem with a custom
RequestListener that captures the current Instance for async requests and invokes release
on it on the FINISHED event (twice as it is responsible for one reference itself).
Comments
Comment by bodewig [ 06/Oct/14 ]
I can't attach anything here, is this correct?
OK, here is my unit test inline
package org.example.jersey_bug;
import
import
import
import
import
import
import
javax.inject.Inject;
javax.ws.rs.GET;
javax.ws.rs.Path;
javax.ws.rs.container.AsyncResponse;
javax.ws.rs.container.Suspended;
javax.ws.rs.core.Application;
javax.ws.rs.core.Response;
import
import
import
import
import
org.glassfish.hk2.api.Factory;
org.glassfish.hk2.utilities.binding.AbstractBinder;
org.glassfish.jersey.process.internal.RequestScoped;
org.glassfish.jersey.server.ResourceConfig;
org.glassfish.jersey.test.JerseyTest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class RequestScopedAndAsyncTest extends JerseyTest {
public static class Injectable {
// just a placeholder
}
public static class InjectableFactory implements Factory<Injectable> {
private static final Object LOCK = new Object();
private static int provided;
private static int balance;
@Override
public Injectable provide() {
synchronized(LOCK) {
provided++;
balance++;
}
return new Injectable();
}
@Override
public void dispose(Injectable i) {
synchronized(LOCK) {
balance--;
}
}
public static void reset() {
synchronized(LOCK) {
provided = balance = 0;
}
}
public static void assertProvidedOne() {
synchronized(LOCK) {
Assert.assertEquals(1, provided);
}
}
public static void assertIsBalanced() {
synchronized(LOCK) {
Assert.assertEquals(0, balance);
}
}
}
@Path("test")
public static class TestResource {
@Inject
private Injectable injectable;
@GET
@Path("sync")
public Response sync() {
return Response.noContent().build();
}
@GET
@Path("async")
public void async(@Suspended AsyncResponse ar) {
ar.resume(Response.noContent().build());
}
}
@Before
public void resetCounters() {
InjectableFactory.reset();
}
@Override
protected Application configure() {
return new ResourceConfig(TestResource.class)
.register(new AbstractBinder() {
@Override
protected void configure() {
bindFactory(InjectableFactory.class)
.to(Injectable.class)
.in(RequestScoped.class);
}
});
}
@Test
public void shouldProvideAndDisposeSync() {
Assert.assertEquals(204,
target("/test/sync").request().get().getStatus());
InjectableFactory.assertProvidedOne();
InjectableFactory.assertIsBalanced();
}
@Test
public void shouldProvideAndDisposeAsync() {
Assert.assertEquals(204,
target("/test/async").request().get().getStatus());
InjectableFactory.assertProvidedOne();
InjectableFactory.assertIsBalanced();
}
}
Comment by Adam Lindenthal [ 09/Oct/14 ]
Hi bodewig, correct - you cannot unfortunatelly attach files to the issue.
But we can - next time just drop a link to github project or whatever (e.g. you can send it via
email to one of us after the communication starts here) and we will attach it for you.
Regarding the problem you are experiencing - this needs to be tested and investigated - thus I
am moving it to backlog.
Thanks,
Adam
PS: should you still have something more to attach here, feel free to drop a link or send a zip to
me.
Comment by Adam Lindenthal [ 19/Feb/15 ]
Fixed in 2.17.
Generated at Tue Feb 09 23:02:19 UTC 2016 using JIRA 6.2.3#6260sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.
Download