This is an automated email from the ASF dual-hosted git repository. dkulp pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/cxf.git
The following commit(s) were added to refs/heads/main by this push: new 728edf1b58 CXF-8885: Eliminate hard refs to `HttpClient` via `HTTPClientPolicy` 728edf1b58 is described below commit 728edf1b589c87715220e753208a5b1ff2a3f0cb Author: Leonard Wörteler <leonard.woerte...@knime.com> AuthorDate: Sat Aug 12 17:22:26 2023 +0200 CXF-8885: Eliminate hard refs to `HttpClient` via `HTTPClientPolicy` There are additional potential references to the `HttpClientFacade` hidden in the property change listeners of `HTTPClientPolicy`. To prevent those from keeping the SelectorManager thread alive, the `HTTPConduit` now registers itself as a listener only via a `WeakReference`, so the conduit can be garbage collected even if the client policy is still referenced inside the SelectorManager thread. --- .../org/apache/cxf/transport/http/HTTPConduit.java | 32 ++++++++++++++++++---- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java index 33b6157559..801eac24e4 100644 --- a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java +++ b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java @@ -26,6 +26,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; +import java.lang.ref.WeakReference; import java.net.HttpRetryException; import java.net.HttpURLConnection; import java.net.MalformedURLException; @@ -298,6 +299,27 @@ public abstract class HTTPConduit private volatile boolean clientSidePolicyCalced; + private final PropertyChangeListener weakRefListener = new WeakPropertyChangeListenerAdapter(this); + + /** + * Change listener that propagates events to this conduit as long as it is alive without holding a hard reference. + */ + private static final class WeakPropertyChangeListenerAdapter implements PropertyChangeListener { + /** Weak reference so the listener can be garbage collected even if it is still registered somewhere. */ + private final WeakReference<PropertyChangeListener> reference; + + WeakPropertyChangeListenerAdapter(PropertyChangeListener inner) { + reference = new WeakReference<>(inner); + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + PropertyChangeListener inner = reference.get(); + if (inner != null) { + inner.propertyChange(evt); + } + } + } /** * Constructor @@ -352,8 +374,8 @@ public abstract class HTTPConduit this, new ClientPolicyCalculator()); if (clientSidePolicy != null) { - clientSidePolicy.removePropertyChangeListener(this); //make sure we aren't added twice - clientSidePolicy.addPropertyChangeListener(this); + clientSidePolicy.removePropertyChangeListener(weakRefListener); //make sure we aren't added twice + clientSidePolicy.addPropertyChangeListener(weakRefListener); } } } @@ -749,7 +771,7 @@ public abstract class HTTPConduit */ public void close() { if (clientSidePolicy != null) { - clientSidePolicy.removePropertyChangeListener(this); + clientSidePolicy.removePropertyChangeListener(weakRefListener); } } @@ -927,8 +949,8 @@ public abstract class HTTPConduit } this.clientSidePolicyCalced = true; this.clientSidePolicy = client; - clientSidePolicy.removePropertyChangeListener(this); //make sure we aren't added twice - clientSidePolicy.addPropertyChangeListener(this); + clientSidePolicy.removePropertyChangeListener(weakRefListener); //make sure we aren't added twice + clientSidePolicy.addPropertyChangeListener(weakRefListener); endpointInfo.setProperty("org.apache.cxf.ws.addressing.replyto", client.getDecoupledEndpoint()); }