Skip to content

Commit 621df7c

Browse files
committed
Add ByteBuf leak detection @rule
This commit introduces a JUnit rule that detects ByteBuf leaks in subclasses of AbstractDataBufferAllocatingTestCase.
1 parent b33d8c6 commit 621df7c

File tree

5 files changed

+56
-12
lines changed

5 files changed

+56
-12
lines changed

spring-core/src/main/java/org/springframework/core/io/buffer/NettyDataBufferFactory.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -49,6 +49,12 @@ public NettyDataBufferFactory(ByteBufAllocator byteBufAllocator) {
4949
this.byteBufAllocator = byteBufAllocator;
5050
}
5151

52+
/**
53+
* Return the {@code ByteBufAllocator} used by this factory.
54+
*/
55+
public ByteBufAllocator getByteBufAllocator() {
56+
return this.byteBufAllocator;
57+
}
5258

5359
@Override
5460
public NettyDataBuffer allocateBuffer() {

spring-core/src/test/java/org/springframework/core/codec/DataBufferDecoderTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@
2828
import org.springframework.core.io.buffer.DataBuffer;
2929
import org.springframework.util.MimeTypeUtils;
3030

31-
import static org.junit.Assert.assertFalse;
32-
import static org.junit.Assert.assertSame;
33-
import static org.junit.Assert.assertTrue;
31+
import static org.junit.Assert.*;
3432

3533
/**
3634
* @author Sebastien Deleuze
@@ -59,5 +57,7 @@ public void decode() {
5957
null, Collections.emptyMap());
6058

6159
assertSame(source, output);
60+
61+
release(fooBuffer, barBuffer);
6262
}
6363
}

spring-core/src/test/java/org/springframework/core/codec/DataBufferEncoderTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@
2828
import org.springframework.core.io.buffer.DataBuffer;
2929
import org.springframework.util.MimeTypeUtils;
3030

31-
import static org.junit.Assert.assertFalse;
32-
import static org.junit.Assert.assertSame;
33-
import static org.junit.Assert.assertTrue;
31+
import static org.junit.Assert.*;
3432

3533
/**
3634
* @author Sebastien Deleuze
@@ -63,6 +61,8 @@ public void encode() {
6361
null, Collections.emptyMap());
6462

6563
assertSame(source, output);
64+
65+
release(fooBuffer, barBuffer);
6666
}
6767

6868
}

spring-core/src/test/java/org/springframework/core/io/buffer/AbstractDataBufferAllocatingTestCase.java

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,16 +18,22 @@
1818

1919
import java.nio.charset.StandardCharsets;
2020
import java.util.Arrays;
21+
import java.util.List;
2122
import java.util.function.Consumer;
2223

24+
import io.netty.buffer.ByteBufAllocator;
25+
import io.netty.buffer.PoolArenaMetric;
2326
import io.netty.buffer.PooledByteBufAllocator;
27+
import io.netty.buffer.PooledByteBufAllocatorMetric;
2428
import io.netty.buffer.UnpooledByteBufAllocator;
29+
import org.junit.Rule;
30+
import org.junit.rules.Verifier;
2531
import org.junit.runner.RunWith;
2632
import org.junit.runners.Parameterized;
2733

2834
import org.springframework.core.io.buffer.support.DataBufferTestUtils;
2935

30-
import static org.junit.Assert.assertEquals;
36+
import static org.junit.Assert.*;
3137

3238
/**
3339
* @author Arjen Poutsma
@@ -43,14 +49,18 @@ public static Object[][] dataBufferFactories() {
4349
return new Object[][] {
4450
{new NettyDataBufferFactory(new UnpooledByteBufAllocator(true))},
4551
{new NettyDataBufferFactory(new UnpooledByteBufAllocator(false))},
46-
{new NettyDataBufferFactory(new PooledByteBufAllocator(true))},
47-
{new NettyDataBufferFactory(new PooledByteBufAllocator(false))},
52+
// disable caching for reliable leak detection, see https://github.com/netty/netty/issues/5275
53+
{new NettyDataBufferFactory(new PooledByteBufAllocator(true, 1, 1, 8192, 11, 0, 0, 0, true))},
54+
{new NettyDataBufferFactory(new PooledByteBufAllocator(false, 1, 1, 8192, 11, 0, 0, 0, true))},
4855
{new DefaultDataBufferFactory(true)},
4956
{new DefaultDataBufferFactory(false)}
5057

5158
};
5259
}
5360

61+
@Rule
62+
public final Verifier leakDetector = new LeakDetector();
63+
5464
protected DataBuffer createDataBuffer(int capacity) {
5565
return this.bufferFactory.allocateBuffer(capacity);
5666
}
@@ -75,4 +85,30 @@ protected Consumer<DataBuffer> stringConsumer(String expected) {
7585
};
7686
}
7787

88+
89+
private class LeakDetector extends Verifier {
90+
91+
@Override
92+
protected void verify() throws Throwable {
93+
if (bufferFactory instanceof NettyDataBufferFactory) {
94+
ByteBufAllocator byteBufAllocator =
95+
((NettyDataBufferFactory) bufferFactory).getByteBufAllocator();
96+
if (byteBufAllocator instanceof PooledByteBufAllocator) {
97+
PooledByteBufAllocator pooledByteBufAllocator =
98+
(PooledByteBufAllocator) byteBufAllocator;
99+
PooledByteBufAllocatorMetric metric = pooledByteBufAllocator.metric();
100+
long allocations = calculateAllocations(metric.directArenas()) +
101+
calculateAllocations(metric.heapArenas());
102+
assertTrue("ByteBuf leak detected: " + allocations +
103+
" allocations were not released", allocations == 0);
104+
}
105+
}
106+
}
107+
108+
private long calculateAllocations(List<PoolArenaMetric> metrics) {
109+
return metrics.stream().mapToLong(PoolArenaMetric::numActiveAllocations).sum();
110+
}
111+
112+
}
113+
78114
}

spring-core/src/test/java/org/springframework/core/io/buffer/DataBufferTests.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -280,6 +280,8 @@ public void growDataBuffer() {
280280
bytes = new byte[9];
281281
buffer.read(bytes);
282282
assertArrayEquals(" World!!!".getBytes(StandardCharsets.UTF_8), bytes);
283+
284+
release(buffer);
283285
}
284286

285287

0 commit comments

Comments
 (0)