Add Netty memory leak detection config property

This commit adds a new `spring.netty.leak-detection` configuration
property that selects the level of memory leak detection for the Netty
engine.

This configuration is applied statically to Netty; this means all
(non-shaded) Netty usages as client or server will be impacted by this
change.

Developers might use this property during development or tests to find
causes of memory leaks when dealing with Netty buffers.

Closes gh-14338
This commit is contained in:
Brian Clozel
2021-03-30 18:05:25 +02:00
parent 66e857f2c5
commit fe1011c23d
7 changed files with 186 additions and 1 deletions

View File

@@ -72,7 +72,7 @@ public class DocumentConfigurationProperties extends DefaultTask {
.addSection("mail").withKeyPrefixes("spring.mail", "spring.sendgrid").addSection("cache")
.withKeyPrefixes("spring.cache").addSection("server").withKeyPrefixes("server").addSection("web")
.withKeyPrefixes("spring.hateoas", "spring.http", "spring.servlet", "spring.jersey", "spring.mvc",
"spring.resources", "spring.session", "spring.web", "spring.webflux")
"spring.netty", "spring.resources", "spring.session", "spring.web", "spring.webflux")
.addSection("json").withKeyPrefixes("spring.jackson", "spring.gson").addSection("rsocket")
.withKeyPrefixes("spring.rsocket").addSection("templating")
.withKeyPrefixes("spring.freemarker", "spring.groovy", "spring.mustache", "spring.thymeleaf")

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.netty;
import io.netty.util.NettyRuntime;
import io.netty.util.ResourceLeakDetector;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Netty.
*
* @author Brian Clozel
* @since 2.5.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(NettyRuntime.class)
@EnableConfigurationProperties(NettyProperties.class)
public class NettyAutoConfiguration {
public NettyAutoConfiguration(NettyProperties properties) {
if (properties.getLeakDetection() != null) {
NettyProperties.LeakDetection leakDetection = properties.getLeakDetection();
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.valueOf(leakDetection.name()));
}
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.netty;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* {@link ConfigurationProperties @ConfigurationProperties} for the Netty engine.
* <p>
* These properties apply globally to the Netty library, used as a client or a server.
*
* @author Brian Clozel
* @since 2.5.0
*/
@ConfigurationProperties(prefix = "spring.netty")
public class NettyProperties {
/**
* Level of leak detection for reference-counted buffers.
*/
private LeakDetection leakDetection = LeakDetection.DISABLED;
public LeakDetection getLeakDetection() {
return this.leakDetection;
}
public void setLeakDetection(LeakDetection leakDetection) {
this.leakDetection = leakDetection;
}
public enum LeakDetection {
/**
* Disable leak detection completely.
*/
DISABLED,
/**
* Detect leaks for 1% of buffers.
*/
SIMPLE,
/**
* Detect leaks for 1% of buffers and track where they were accessed.
*/
ADVANCED,
/**
* Detect leaks for 100% of buffers and track where they were accessed.
*/
PARANOID
}
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Auto-configuration for the Netty library.
*/
package org.springframework.boot.autoconfigure.netty;

View File

@@ -1770,6 +1770,10 @@
"name": "spring.webservices.wsdl-locations",
"type": "java.util.List<java.lang.String>",
"description": "Comma-separated list of locations of WSDLs and accompanying XSDs to be exposed as beans."
},
{
"name": "spring.netty.leak-detection",
"defaultValue": "disabled"
}
],
"hints": [

View File

@@ -105,6 +105,7 @@ org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration,\
org.springframework.boot.autoconfigure.netty.NettyAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.netty;
import io.netty.util.ResourceLeakDetector;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link NettyAutoConfiguration}.
*
* @author Brian Clozel
*/
public class NettyAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(NettyAutoConfiguration.class));
@Test
void leakDetectionShouldBeConfigured() {
this.contextRunner.withPropertyValues("spring.netty.leak-detection=paranoid").run((context) -> {
assertThat(ResourceLeakDetector.getLevel()).isEqualTo(ResourceLeakDetector.Level.PARANOID);
// reset configuration for the following tests.
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED);
});
}
}