eclipse-ee4j / eclipse-ee4j/jersey
@BeanParam injection behavior changed with 2.17
- Dominant language
- Java
- Stars
- 730
- Forks
- 382
- PR merge metrics
- No merged PRs in 30d
Description
Hi.
We're using Jersey 2.16 with JDK 1.7.0_55-b13 64 bit and Tomcat 7.0.21 under Windows 7 to build a REST api.
Now, we're facing a problem with memory usage during load. We've created a TestNG testcase method, that
performs CRUD operations 10 times in a loop. That method is invoked 1000 times by 50 concurrent threads.
After approx. 30 minutes, the server gets slower and slower until it gets an OutOfMemoryException. We
created a ThreadDump with jvisualvm and used Eclipse Memory Analyzer to get to the root problem.
It seems that hk2's SystemDescriptor is eating memory like a boss . Here's the output of the analyzer:
170.088 instances of "org.jvnet.hk2.internal.SystemDescriptor",
loaded by "org.apache.catalina.loader.WebappClassLoader @ 0xc026bd80"
occupy 625.581.408 (92,47%) bytes.
These instances are referenced from one instance of "org.jvnet.hk2.internal.ServiceLocatorImpl",
loaded by "org.apache.catalina.loader.WebappClassLoader @ 0xc026bd80"
We already found an old JIRA ticket regarding a SystemDescriptor memory leak:
[https://java.net/jira/browse/HK2-205[https://java.net/jira/browse/HK2-205](https://java.net/jira/browse/HK2-205[https://java.net/jira/browse/HK2-205)]
that was fixed in 2.3.0.
So we switched to the latest hk2 version, 2.4.0-b16\. But without any effect.
---------
Meanwhile we came to the same results as reported here:
[https://java.net/jira/browse/JERSEY-2800](https://java.net/jira/browse/JERSEY-2800)
It also got filled up with @BeanParams classes.
Then we switched to 2.17 and found out, that the @BeanParam class (PathContext) is missing some functionality.
It looks like that:
public class PathContext {
@PathParam(TenantResource.TENANT_ID_PATH_PARAM)
private String tenantId;
@PathParam(AccountResource.ACCOUNT_ID_PATH_PARAM)
private String accountId;
@PathParam(RepositoryResource.REPOSITORY_ID_PATH_PARAM)
private String repositoryId;
@PathParam(RepositoryEntryResource.REPOSITORY_ENTRY_ID_PATH_PARAM)
private String repositoryEntryId;
....
With 2.16 and prior, Calling a URL like this:
[http://localhost:8080/something/api/1/tenants/b38c7e6b-f17f-45bf-a746-65b40f95d845/repositories/1ee83a90-6e2f-435c-ac6a-ece0f5106671/entries](http://localhost:8080/something/api/1/tenants/b38c7e6b-f17f-45bf-a746-65b40f95d845/repositories/1ee83a90-6e2f-435c-ac6a-ece0f5106671/entries)
Resulted into filled tenantId and repositoryId.
Now, only tenantId is filled - although repositoryId should also be accessible.
I can also confirm, that now only one instance of PathContext is created (using @PostConstruct).
With 2.16 it were 3: 1st with only tenantId set, the other 2 instances had repositoryId correctly set.
PathContext is injected into different resources as field member. Resources are accessed via Subresourcelocators.
So I'm wondering if the fix from #3072 maybe broke some other stuff?
I would expect, if I inject the PathContext anywhere, it should parse the complete URL for the specified @PathParams.
This didn't seem to happen anymore.
* * *
Please find attached a small testcase that shows the problem.
It's quite ugly (I reused it from an Apache CXF testcase), but should be enough for demonstration.
It's a maven project that includes a war. If you execute "mvn clean install", it will automatically
start a tomcat container via cargo, deploys the war, and execute the JerseyIT test.
The test itself simply invokes an endpoint (RepositoryEntryResourceImpl)
and sends an entryId to it (url: [http://localhost:8080/test/api/repositories/0815/entries/0816](http://localhost:8080/test/api/repositories/0815/entries/0816)).
The endpoint reads from the injected PathContext the entryId and returns it to the testcase. It expects that
0816 is returned.
It should work with 2.16\. If you change the version to 2.17 in the pom, it should fail with a null
returned from the endpoint.
If you take a look at the server log, the following is shown:
2.16:
Apr 29, 2015 5:54:55 PM test.PathContext postConstruct
INFO: hashCode: 556592017, repositoryId: 0815, entryId: null
Apr 29, 2015 5:54:55 PM test.PathContext postConstruct
INFO: hashCode: 29437898, repositoryId: 0815, entryId: 0816
Apr 29, 2015 5:54:55 PM test.RepositoryEntryResourceImpl getEntry
INFO: injected pathContext: hashCode: 29437898, repositoryId: 0815, entryId: 0816
Actually PathContext is created twice. Once for every endpoint. The 2nd instance
(for RepositoryEntryResourceImpl) now contains the correct entryId.
2.17:
Apr 29, 2015 5:58:28 PM test.PathContext postConstruct
INFO: hashCode: 1730327498, repositoryId: 0815, entryId: null
Apr 29, 2015 5:58:28 PM test.RepositoryEntryResourceImpl getEntry
INFO: injected pathContext: hashCode: 1730327498, repositoryId: 0815, entryId: null
Here, PathContext is only created once. Same instance is injected only once
into the different endpoints. Also entryId is null.
I hope that helps tracking down the problem.
#### Environment
Jersey 2.17, JDK 1.7.0_55-b13 64 bit, Tomcat 7.0.21, Windows 7
#### Affected Versions
[2.17]
Contributor guide
Assessment
This issue has not been assessed yet.