Skip to content
This repository was archived by the owner on Dec 12, 2022. It is now read-only.

Commit dc281c7

Browse files
committed
Buffers always have a cleaner attached
Motivation: Although having a cleaner attached adds a bit of overhead when allocating or closing buffers, it is more important to make our systems, libraries and frameworks misuse resistant and safe by default. Modification: Remove the ability to allocate a buffer that does not have a cleaner attached. Reference counting and the ability to explicitly release memory remains. This just makes sure that we always have a safety net to fall back on. Result: This will make systems less prone to crashes through running out of memory, native or otherwise, even in the face of true memory leaks. (Leaks through retained strong references cannot be fixed in any way)
1 parent 1013c33 commit dc281c7

File tree

6 files changed

+14
-46
lines changed

6 files changed

+14
-46
lines changed

src/main/java/io/netty/buffer/api/Allocator.java

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,10 @@ default void close() {
150150
}
151151

152152
static Allocator heap() {
153-
return new ManagedAllocator(MemoryManager.getHeapMemoryManager(), null);
153+
return new ManagedAllocator(MemoryManager.getHeapMemoryManager(), Statics.CLEANER);
154154
}
155155

156156
static Allocator direct() {
157-
return new ManagedAllocator(MemoryManager.getNativeMemoryManager(), null);
158-
}
159-
160-
static Allocator directWithCleaner() {
161157
return new ManagedAllocator(MemoryManager.getNativeMemoryManager(), Statics.CLEANER);
162158
}
163159

@@ -168,13 +164,4 @@ static Allocator pooledHeap() {
168164
static Allocator pooledDirect() {
169165
return new SizeClassedMemoryPool(MemoryManager.getNativeMemoryManager());
170166
}
171-
172-
static Allocator pooledDirectWithCleaner() {
173-
return new SizeClassedMemoryPool(MemoryManager.getNativeMemoryManager()) {
174-
@Override
175-
protected Drop<Buf> getDrop() {
176-
return new NativeMemoryCleanerDrop(this, getMemoryManager(), super.getDrop());
177-
}
178-
};
179-
}
180167
}

src/main/java/io/netty/buffer/api/NativeMemoryCleanerDrop.java renamed to src/main/java/io/netty/buffer/api/CleanerPooledDrop.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,17 @@
2424
import static io.netty.buffer.api.Statics.findVarHandle;
2525
import static java.lang.invoke.MethodHandles.lookup;
2626

27-
class NativeMemoryCleanerDrop implements Drop<Buf> {
27+
class CleanerPooledDrop implements Drop<Buf> {
2828
private static final VarHandle CLEANABLE =
29-
findVarHandle(lookup(), NativeMemoryCleanerDrop.class, "cleanable", GatedCleanable.class);
29+
findVarHandle(lookup(), CleanerPooledDrop.class, "cleanable", GatedCleanable.class);
3030
private final SizeClassedMemoryPool pool;
3131
private final MemoryManager manager;
3232
private final Drop<Buf> delegate;
3333
@SuppressWarnings("unused")
3434
private volatile GatedCleanable cleanable;
3535

36-
NativeMemoryCleanerDrop(SizeClassedMemoryPool pool, MemoryManager manager,
37-
Drop<Buf> delegate) {
36+
CleanerPooledDrop(SizeClassedMemoryPool pool, MemoryManager manager,
37+
Drop<Buf> delegate) {
3838
this.pool = pool;
3939
this.manager = manager;
4040
this.delegate = delegate;

src/main/java/io/netty/buffer/api/SizeClassedMemoryPool.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ protected Buf createBuf(int size, Drop<Buf> drop) {
5959
}
6060

6161
protected Drop<Buf> getDrop() {
62-
return this;
62+
return new CleanerPooledDrop(this, getMemoryManager(), this);
6363
}
6464

6565
@Override

src/test/java/io/netty/buffer/api/BufTest.java

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,9 @@ static Fixture[] allocators() {
6868
static List<Fixture> initialAllocators() {
6969
return List.of(
7070
new Fixture("heap", Allocator::heap, HEAP),
71-
new Fixture("direct", Allocator::direct, DIRECT),
72-
new Fixture("directWithCleaner", Allocator::directWithCleaner, DIRECT, CLEANER),
71+
new Fixture("direct", Allocator::direct, DIRECT, CLEANER),
7372
new Fixture("pooledHeap", Allocator::pooledHeap, POOLED, HEAP),
74-
new Fixture("pooledDirect", Allocator::pooledDirect, POOLED, DIRECT),
75-
new Fixture("pooledDirectWithCleaner", Allocator::pooledDirectWithCleaner, POOLED, DIRECT, CLEANER));
73+
new Fixture("pooledDirect", Allocator::pooledDirect, POOLED, DIRECT, CLEANER));
7674
}
7775

7876
static Stream<Fixture> nonSliceAllocators() {
@@ -87,18 +85,10 @@ static Stream<Fixture> directAllocators() {
8785
return fixtureCombinations().filter(Fixture::isDirect);
8886
}
8987

90-
static Stream<Fixture> directWithCleanerAllocators() {
91-
return fixtureCombinations().filter(f -> f.isDirect() && f.isCleaner());
92-
}
93-
94-
static Stream<Fixture> directPooledWithCleanerAllocators() {
88+
static Stream<Fixture> directPooledAllocators() {
9589
return fixtureCombinations().filter(f -> f.isDirect() && f.isCleaner() && f.isPooled());
9690
}
9791

98-
static Stream<Fixture> poolingAllocators() {
99-
return fixtureCombinations().filter(f -> f.isPooled());
100-
}
101-
10292
private static Stream<Fixture> fixtureCombinations() {
10393
Fixture[] fxs = fixtures;
10494
if (fxs != null) {
@@ -1496,7 +1486,7 @@ public void directBufferMustHaveNonZeroAddress(Fixture fixture) {
14961486
class CleanerTests {
14971487
@Disabled("Precise native memory accounting does not work since recent panama-foreign changes.")
14981488
@ParameterizedTest
1499-
@MethodSource("io.netty.buffer.api.BufTest#directWithCleanerAllocators")
1489+
@MethodSource("io.netty.buffer.api.BufTest#directAllocators")
15001490
public void bufferMustBeClosedByCleaner(Fixture fixture) throws InterruptedException {
15011491
var allocator = fixture.createAllocator();
15021492
allocator.close();
@@ -1518,7 +1508,7 @@ private void allocateAndForget(Allocator allocator, int size) {
15181508

15191509
@Disabled("Precise native memory accounting does not work since recent panama-foreign changes.")
15201510
@ParameterizedTest
1521-
@MethodSource("io.netty.buffer.api.BufTest#directPooledWithCleanerAllocators")
1511+
@MethodSource("io.netty.buffer.api.BufTest#directPooledAllocators")
15221512
public void buffersMustBeReusedByPoolingAllocatorEvenWhenDroppedByCleanerInsteadOfExplicitly(Fixture fixture)
15231513
throws InterruptedException {
15241514
try (var allocator = fixture.createAllocator()) {

src/test/java/io/netty/buffer/api/benchmarks/MemorySegmentClosedByCleanerBenchmark.java

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,7 @@
4242
@State(Scope.Benchmark)
4343
public class MemorySegmentClosedByCleanerBenchmark {
4444
private static final Allocator direct = Allocator.direct();
45-
private static final Allocator withCleaner = Allocator.directWithCleaner();
4645
private static final Allocator directPooled = Allocator.pooledDirect();
47-
private static final Allocator pooledWithCleaner = Allocator.pooledDirectWithCleaner();
4846

4947
@Param({"heavy", "light"})
5048
public String workload;
@@ -77,19 +75,12 @@ public Buf explicitPooledClose() throws Exception {
7775

7876
@Benchmark
7977
public Buf cleanerClose() throws Exception {
80-
return process(withCleaner.allocate(256));
78+
return process(direct.allocate(256));
8179
}
8280

8381
@Benchmark
8482
public Buf cleanerClosePooled() throws Exception {
85-
return process(pooledWithCleaner.allocate(256));
86-
}
87-
88-
@Benchmark
89-
public Buf pooledWithCleanerExplicitClose() throws Exception {
90-
try (Buf buf = pooledWithCleaner.allocate(256)) {
91-
return process(buf);
92-
}
83+
return process(directPooled.allocate(256));
9384
}
9485

9586
private Buf process(Buf buffer) throws Exception {

src/test/java/io/netty/buffer/api/examples/AsyncExample.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
public final class AsyncExample {
2424
public static void main(String[] args) throws Exception {
25-
try (Allocator allocator = Allocator.pooledDirectWithCleaner();
25+
try (Allocator allocator = Allocator.pooledDirect();
2626
Buf startBuf = allocator.allocate(16)) {
2727
startBuf.writeLong(threadId());
2828

0 commit comments

Comments
 (0)