Skip to content

Commit cc27b4c

Browse files
committed
Convert OpenChannelFutureListener to a static nested class
Explicit NettyStream dependency instead of the implicit enclosing instance, removing the this$0 capture footgun that caused JAVA-6250. No behavioral change. JAVA-6250
1 parent 9767295 commit cc27b4c

1 file changed

Lines changed: 12 additions & 10 deletions

File tree

driver-core/src/main/com/mongodb/internal/connection/netty/NettyStream.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ public void initChannel(final SocketChannel ch) {
221221
}
222222
});
223223
ChannelFuture channelFuture = bootstrap.connect(nextAddress);
224-
channelFuture.addListener(new OpenChannelFutureListener(operationContext, socketAddressQueue, channelFuture, handler));
224+
channelFuture.addListener(new OpenChannelFutureListener(this, operationContext, socketAddressQueue, channelFuture, handler));
225225
}
226226
}
227227

@@ -507,15 +507,17 @@ public T get() throws IOException {
507507
}
508508
}
509509

510-
private class OpenChannelFutureListener implements ChannelFutureListener {
510+
private static final class OpenChannelFutureListener implements ChannelFutureListener {
511+
private final NettyStream stream;
511512
private final Queue<SocketAddress> socketAddressQueue;
512513
private final ChannelFuture channelFuture;
513514
private final AsyncCompletionHandler<Void> handler;
514515
private final OperationContext operationContext;
515516

516-
OpenChannelFutureListener(final OperationContext operationContext,
517+
OpenChannelFutureListener(final NettyStream stream, final OperationContext operationContext,
517518
final Queue<SocketAddress> socketAddressQueue, final ChannelFuture channelFuture,
518519
final AsyncCompletionHandler<Void> handler) {
520+
this.stream = stream;
519521
this.operationContext = operationContext;
520522
this.socketAddressQueue = socketAddressQueue;
521523
this.channelFuture = channelFuture;
@@ -524,24 +526,24 @@ private class OpenChannelFutureListener implements ChannelFutureListener {
524526

525527
@Override
526528
public void operationComplete(final ChannelFuture future) {
527-
withLock(lock, () -> {
529+
withLock(stream.lock, () -> {
528530
if (future.isSuccess()) {
529-
if (isClosed) {
531+
if (stream.isClosed) {
530532
channelFuture.channel().close();
531533
} else {
532-
channel = channelFuture.channel();
534+
stream.channel = channelFuture.channel();
533535
// CloseChannelFutureListener captures only the NettyStream, never OpenChannelFutureListener.this,
534536
// so the one-shot connection-open handler is not pinned for the lifetime of the pooled channel (JAVA-6250)
535-
channel.closeFuture().addListener(new CloseChannelFutureListener(NettyStream.this));
537+
stream.channel.closeFuture().addListener(new CloseChannelFutureListener(stream));
536538
}
537539
handler.completed(null);
538540
} else {
539-
if (isClosed) {
541+
if (stream.isClosed) {
540542
handler.completed(null);
541543
} else if (socketAddressQueue.isEmpty()) {
542-
handler.failed(new MongoSocketOpenException("Exception opening socket", getAddress(), future.cause()));
544+
handler.failed(new MongoSocketOpenException("Exception opening socket", stream.getAddress(), future.cause()));
543545
} else {
544-
initializeChannel(operationContext, handler, socketAddressQueue);
546+
stream.initializeChannel(operationContext, handler, socketAddressQueue);
545547
}
546548
}
547549
});

0 commit comments

Comments
 (0)