Skip to content
This repository was archived by the owner on May 28, 2018. It is now read-only.

Commit f538118

Browse files
Petr Boudapavelbucek
authored andcommitted
Injectee incoming from Jersey side is implemented by a different type than from the HK2 side.
Memory leak occurs because Injectee from Jersey side does not contain hashCode. Change-Id: I2a56f9f6b5c3cbd7dedc112e66b2f983e198f6e6
1 parent f75b53c commit f538118

File tree

1 file changed

+61
-16
lines changed

1 file changed

+61
-16
lines changed

inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/ContextInjectionResolverImpl.java

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import java.lang.reflect.Type;
4545
import java.util.HashSet;
4646
import java.util.List;
47+
import java.util.Objects;
4748
import java.util.Set;
4849
import java.util.function.Function;
4950

@@ -100,14 +101,8 @@ protected void configure() {
100101
@Inject
101102
private ServiceLocator serviceLocator;
102103

103-
private final Cache<Injectee, ActiveDescriptor<?>> descriptorCache
104-
= new Cache<Injectee, ActiveDescriptor<?>>(new Function<Injectee, ActiveDescriptor<?>>() {
105-
106-
@Override
107-
public ActiveDescriptor<?> apply(Injectee key) {
108-
return serviceLocator.getInjecteeDescriptor(key);
109-
}
110-
});
104+
private final Cache<CacheKey, ActiveDescriptor<?>> descriptorCache
105+
= new Cache<>(cacheKey -> serviceLocator.getInjecteeDescriptor(cacheKey.injectee));
111106

112107
@Override
113108
public Object resolve(Injectee injectee, ServiceHandle<?> root) {
@@ -118,10 +113,10 @@ public Object resolve(Injectee injectee, ServiceHandle<?> root) {
118113
if (isHk2Factory) {
119114
newInjectee = getFactoryInjectee(injectee, ReflectionHelper.getTypeArgument(requiredType, 0));
120115
} else {
121-
newInjectee = foreignRequestScopedInjecteeCache.apply(injectee);
116+
newInjectee = foreignRequestScopedInjecteeCache.apply(new CacheKey(injectee));
122117
}
123118

124-
ActiveDescriptor<?> ad = descriptorCache.apply(newInjectee);
119+
ActiveDescriptor<?> ad = descriptorCache.apply(new CacheKey(newInjectee));
125120

126121
if (ad != null) {
127122
final ServiceHandle handle = serviceLocator.getServiceHandle(ad, newInjectee);
@@ -144,6 +139,13 @@ public Object resolve(Injectee injectee, ServiceHandle<?> root) {
144139
*/
145140
@Override
146141
public Object resolve(org.glassfish.jersey.internal.inject.Injectee injectee) {
142+
InjecteeImpl hk2injectee = toInjecteeImpl(injectee);
143+
144+
// Delegate the call to HK2 Resolver, Service Handle is not need in the delegated processing.
145+
return resolve(hk2injectee, null);
146+
}
147+
148+
private static InjecteeImpl toInjecteeImpl(org.glassfish.jersey.internal.inject.Injectee injectee) {
147149
InjecteeImpl hk2injectee = new InjecteeImpl() {
148150
@Override
149151
public Class<?> getInjecteeClass() {
@@ -152,12 +154,11 @@ public Class<?> getInjecteeClass() {
152154
};
153155
hk2injectee.setRequiredType(injectee.getRequiredType());
154156
hk2injectee.setRequiredQualifiers(injectee.getRequiredQualifiers());
157+
hk2injectee.setParent(injectee.getParent());
155158
if (injectee.getInjecteeDescriptor() != null) {
156159
hk2injectee.setInjecteeDescriptor((ActiveDescriptor<?>) injectee.getInjecteeDescriptor().get());
157160
}
158-
159-
// Delegate the call to HK2 Resolver, Service Handle is not need in the delegated processing.
160-
return resolve(hk2injectee, null);
161+
return hk2injectee;
161162
}
162163

163164
private Factory asFactory(final ServiceHandle handle) {
@@ -206,9 +207,10 @@ public Class<Context> getAnnotation() {
206207
return Context.class;
207208
}
208209

209-
private final Cache<Injectee, Injectee> foreignRequestScopedInjecteeCache = new Cache<>(new Function<Injectee, Injectee>() {
210+
private final Cache<CacheKey, Injectee> foreignRequestScopedInjecteeCache = new Cache<>(new Function<CacheKey, Injectee>() {
210211
@Override
211-
public Injectee apply(Injectee injectee) {
212+
public Injectee apply(CacheKey cacheKey) {
213+
Injectee injectee = cacheKey.getInjectee();
212214
if (injectee.getParent() != null) {
213215
if (Field.class.isAssignableFrom(injectee.getParent().getClass())) {
214216
Field f = (Field) injectee.getParent();
@@ -235,7 +237,7 @@ public Injectee apply(Injectee injectee) {
235237

236238
private Set<Class<?>> getForeignRequestScopedComponents() {
237239
final List<ForeignRequestScopeBridge> scopeBridges = serviceLocator.getAllServices(ForeignRequestScopeBridge.class);
238-
final Set<Class<?>> result = new HashSet<Class<?>>();
240+
final Set<Class<?>> result = new HashSet<>();
239241
for (ForeignRequestScopeBridge bridge : scopeBridges) {
240242
final Set<Class<?>> requestScopedComponents = bridge.getRequestScopedComponents();
241243
if (requestScopedComponents != null) {
@@ -244,4 +246,47 @@ private Set<Class<?>> getForeignRequestScopedComponents() {
244246
}
245247
return result;
246248
}
249+
250+
/**
251+
* Key dedicated for internal cache mechanism because two different {@link Injectee} Hk2 implementations comes from
252+
* Jersey side and HK2 side injection resolver.
253+
*/
254+
private static class CacheKey {
255+
256+
private final Injectee injectee;
257+
258+
private final int hash;
259+
260+
private CacheKey(Injectee injectee) {
261+
this.injectee = injectee;
262+
263+
this.hash = Objects.hash(injectee.getInjecteeClass(),
264+
injectee.getInjecteeDescriptor(),
265+
injectee.getParent(),
266+
injectee.getRequiredQualifiers(),
267+
injectee.getRequiredType(),
268+
injectee.getPosition());
269+
}
270+
271+
private Injectee getInjectee() {
272+
return injectee;
273+
}
274+
275+
@Override
276+
public boolean equals(Object o) {
277+
if (this == o) {
278+
return true;
279+
}
280+
if (!(o instanceof CacheKey)) {
281+
return false;
282+
}
283+
CacheKey cacheKey = (CacheKey) o;
284+
return this.hash == cacheKey.hash;
285+
}
286+
287+
@Override
288+
public int hashCode() {
289+
return hash;
290+
}
291+
}
247292
}

0 commit comments

Comments
 (0)