You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by re...@apache.org on 2023/08/11 03:17:04 UTC
[cxf] 01/02: [CXF-8885] Eliminate hidden reference to `HttpClient` in `ProxySelector` (#1377)
This is an automated email from the ASF dual-hosted git repository.
reta pushed a commit to branch 3.6.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git
commit 4410892ad37e906863e7a996f543c5b503dcc666
Author: Leo Wörteler <le...@woerteler.de>
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.
(cherry picked from commit e204d71ce0a2d4af2ed2299c34c49c9ac094dfe4)
---
.../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 0451e9af68..44c5785ca8 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;