This is an automated email from the ASF dual-hosted git repository.

reta 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 e204d71ce0 [CXF-8885] Eliminate hidden reference to `HttpClient` in 
`ProxySelector` (#1377)
e204d71ce0 is described below

commit e204d71ce0a2d4af2ed2299c34c49c9ac094dfe4
Author: Leo Wörteler <[email protected]>
AuthorDate: Fri Aug 11 01:40:53 2023 +0200

    [CXF-8885] Eliminate hidden reference to `HttpClient` in `ProxySelector` 
(#1377)
    
    The SelectorManager thread of the WebClient would normally shut down
    after the HttpClient's outer shell, the `HttpClientFacade` has been
    garbage collected. Unfortunately the `ProxySelector` instance created in
    `HttpClientHTTPConduit` is a non-static (anonymous) subclass, so it
    retains a hard reference to the enclosing `HttpClientHTTPConduit`
    instance and therefore also its `client` field. This gives the
    SelectorManager thread a hard reference to the `HttpClientFacade`, so
    the facade can never be garbage collected and the thread never shuts
    down. Making the class static solves the problem.
---
 .../cxf/transport/http/HttpClientHTTPConduit.java  | 40 ++++++++++++++++------
 1 file changed, 29 insertions(+), 11 deletions(-)

diff --git 
a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpClientHTTPConduit.java
 
b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpClientHTTPConduit.java
index a9e9f51830..e16f9d3b48 100644
--- 
a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpClientHTTPConduit.java
+++ 
b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpClientHTTPConduit.java
@@ -206,17 +206,7 @@ public class HttpClientHTTPConduit extends 
URLConnectionHTTPConduit {
         HttpClient cl = client;
         if (cl == null) {
             int ctimeout = determineConnectionTimeout(message, csPolicy);      
  
-            ProxySelector ps = new ProxySelector() {
-                public List<Proxy> select(URI uri) {
-                    Proxy proxy = proxyFactory.createProxy(csPolicy, uri);
-                    if (proxy !=  null) {
-                        return Arrays.asList(proxy);
-                    }
-                    return ProxySelector.getDefault().select(uri);
-                }
-                public void connectFailed(URI uri, SocketAddress sa, 
IOException ioe) {
-                }
-            };
+            ProxySelector ps = new ProxyFactoryProxySelector(proxyFactory, 
csPolicy);
             
             HttpClient.Builder cb = HttpClient.newBuilder()
                 .proxy(ps)
@@ -309,6 +299,34 @@ public class HttpClientHTTPConduit extends 
URLConnectionHTTPConduit {
     }
 
 
+    /**
+     * This class <i>must</i> be static so it doesn't capture a reference to 
{@code HttpClientHTTPConduit.this} and
+     * through that to {@link HttpClientHTTPConduit#client}. Otherwise the 
client can never be garbage collected, which
+     * means that the companion "SelectorManager" thread keeps running 
indefinitely (see CXF-8885).
+     */
+    private static final class ProxyFactoryProxySelector extends ProxySelector 
{
+        private final ProxyFactory proxyFactory;
+        private final HTTPClientPolicy csPolicy;
+
+        ProxyFactoryProxySelector(ProxyFactory proxyFactory, HTTPClientPolicy 
csPolicy) {
+            this.proxyFactory = proxyFactory;
+            this.csPolicy = csPolicy;
+        }
+
+        @Override
+        public List<Proxy> select(URI uri) {
+            Proxy proxy = proxyFactory.createProxy(csPolicy, uri);
+            if (proxy !=  null) {
+                return Arrays.asList(proxy);
+            }
+            return ProxySelector.getDefault().select(uri);
+        }
+
+        @Override
+        public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
+        }
+    }
+
     class HttpClientWrappedOutputStream extends WrappedOutputStream {
         List<Flow.Subscriber<? super ByteBuffer>> subscribers = new 
LinkedList<>();
         CompletableFuture<HttpResponse<InputStream>> future;

Reply via email to