Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

JettyClientHttpConnector buffer leak in Spring Framework 6.2 #35319

Closed
Assignees
Labels
in: webIssues in web modules (web, webmvc, webflux, websocket) type: regressionA bug that is also a regression
Milestone
@Kerry-G

Description

Spring Framework 6.2 introduces a buffer leak when using JettyClientHttpConnector with a Jetty's httpClient. This worked correctly in Spring Framework 6.1.

We tested this against all 6.2.x version and 6.1.x version. Always produce leaky buffers on 6.2.x. and it is always fine with versions 6.1.x.

In this example, we use ArrayByteBufferPool.Tracking to make it obvious there is a buffer leak, but in our actual project, we use the default implementation of ArrayByteBufferPool.

Here's a OneDrive link to an actual project but also the code here if you don't want to download external files:

# .\spring-memory-leak-test\src\main\java\com\test\spring\WebClientBuilderStoreExecutor.java
package com.test.spring;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.transport.HttpClientTransportDynamic;
import org.eclipse.jetty.io.ArrayByteBufferPool;
import org.eclipse.jetty.io.ArrayByteBufferPool.Tracking;
import org.eclipse.jetty.io.ClientConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.springframework.http.client.reactive.JettyClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
public class WebClientBuilderStoreExecutor {
 public static void main(String[] args) throws Exception {
 ClientConnector clientConnector = new ClientConnector();
 HttpClient httpClient = new HttpClient(new HttpClientTransportDynamic(clientConnector));
 Tracking tracking = new Tracking();
 httpClient.setByteBufferPool(tracking);
 WebClient client = WebClient.builder()
 .clientConnector(new JettyClientHttpConnector(httpClient))
 .build();
 Map<Integer, String> results = new ConcurrentHashMap<>();
 ExecutorService executor = Executors.newFixedThreadPool(50);
 for (int i = 0; i < 10; i++) {
 final int index = i;
 executor.submit(
 () -> {
 String block =
 client.get()
 .uri("http://httpbin.org/anything")
 .retrieve()
 .bodyToMono(String.class)
 .block();
 results.put(index, block);
 });
 }
 executor.shutdown();
 executor.awaitTermination(60, TimeUnit.SECONDS);
 System.out.println(
 "Completed request. Results stored in HashMap with "
 + results.size()
 + " entries.");
 System.out.println("Leaks count: " + tracking.getLeaks().size());
 tracking.getLeaks().forEach(leaks -> System.out.println("Leaked buffers: " + leaks));
 }
}
# \spring-memory-leak-test\pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.test.spring</groupId>
	<artifactId>spring-leak-test</artifactId>
	<packaging>jar</packaging>
	<version>1.0-SNAPSHOT</version>
	<name></name>
	<url>http://maven.apache.org</url>
	<properties>
		<jetty-reactive-httpclient.version>4.0.10</jetty-reactive-httpclient.version>
		<!-- <spring-boot.version>3.5.4</spring-boot.version>
 	<spring.version>6.2.9</spring.version> -->
		<spring-boot.version>3.3.12</spring-boot.version>
 	<spring.version>6.1.20</spring.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.eclipse.jetty</groupId>
			<artifactId>jetty-reactive-httpclient</artifactId>
			<version>${jetty-reactive-httpclient.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-webflux</artifactId>
			<version>${spring-boot.version}</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>17</source>
					<target>17</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<configuration>
					<archive>
						<manifest>
							<addClasspath>true</addClasspath>
							<classpathPrefix>lib/</classpathPrefix>
							<mainClass>com.test.spring.WebClientBuilderStore</mainClass>
						</manifest>
					</archive>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-assembly-plugin</artifactId>
				<configuration>
					<archive>
						<manifest>
							<mainClass>com.test.spring.WebClientBuilderStore</mainClass>
						</manifest>
					</archive>
					<descriptorRefs>
						<descriptorRef>jar-with-dependencies</descriptorRef>
					</descriptorRefs>
				</configuration>
				<executions>
					<execution>
						<id>make-assembly</id>
						<phase>package</phase>
						<goals>
							<goal>single</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket) type: regressionA bug that is also a regression

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    AltStyle によって変換されたページ (->オリジナル) /