Skip to content

Commit

Permalink
WELD-2750 Tweak how parent-child creational contexts are created. Use…
Browse files Browse the repository at this point in the history
… WeakReference to keep track of destroyed instance.
  • Loading branch information
manovotn committed Aug 4, 2023
1 parent 151019b commit 800fea3
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;

import jakarta.enterprise.context.spi.Contextual;
import jakarta.enterprise.context.spi.CreationalContext;
Expand Down Expand Up @@ -62,7 +62,12 @@ public class CreationalContextImpl<T> implements CreationalContext<T>, WeldCreat

private final CreationalContextImpl<?> parentCreationalContext;

// Precondition for access when non-null: synchronized (dependentInstances)
/**
* Needs to be always initialized as a Set that managed WeakReferences to avoid cyclic references and leaks.
* Precondition for access when non-null: synchronized (dependentInstances).
*
* @see #initDestroyedIfNeeded()
*/
private transient Set<ContextualInstance<?>> destroyed;

private transient List<ResourceReference<?>> resourceReferences;
Expand Down Expand Up @@ -149,19 +154,15 @@ public void release(Contextual<T> contextual, T instance) {

private <T> void destroy(ContextualInstance<T> beanInstance) {
// Precondition: synchronized (dependentInstances)
if (this.destroyed == null) {
this.destroyed = new HashSet<>();
}
initDestroyedIfNeeded();
if (this.destroyed.add(beanInstance)) {
beanInstance.getContextual().destroy(beanInstance.getInstance(), beanInstance.getCreationalContext());
}
}

private <T> void release(ContextualInstance<T> beanInstance) {
// Precondition: synchronized (dependentInstances)
if (this.destroyed == null) {
this.destroyed = new HashSet<>();
}
initDestroyedIfNeeded();
if (this.destroyed.add(beanInstance)) {
CreationalContext<T> cc = beanInstance.getCreationalContext();
if (cc instanceof CreationalContextImpl<?>) {
Expand Down Expand Up @@ -311,4 +312,11 @@ private Object readResolve() throws ObjectStreamException {

}

private void initDestroyedIfNeeded() {
// we need to use WeakReference set so that we avoid cyclic references and memory leaks
if (this.destroyed == null) {
this.destroyed = Collections.newSetFromMap(new WeakHashMap<>());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,13 @@ public Object getInjectableReference(InjectionPoint injectionPoint, Bean<?> reso
}
}
}
return getReference(resolvedBean, requestedType, creationalContext, delegateInjectionPoint);
// #getReference always creates a child CC and links it to the CC we pass an argument
// This is exactly what we want for dependent beans but all other beans shouldn't have that
if (Dependent.class.equals(resolvedBean.getScope())) {
return getReference(resolvedBean, requestedType, creationalContext, delegateInjectionPoint);
} else {
return getReference(resolvedBean, requestedType, createCreationalContext(null), delegateInjectionPoint);
}

} finally {
stack.pop();
Expand Down

0 comments on commit 800fea3

Please sign in to comment.