diff --git a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java index 5bfc253c6ba..a2cefbddcfa 100644 --- a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1864,22 +1864,7 @@ private void implCloseBlockingMode() throws IOException { registry.invalidateAll(); if (!tryClose()) { - long reader = readerThread; - long writer = writerThread; - if (reader != 0 || writer != 0) { - if (NativeThread.isVirtualThread(reader) - || NativeThread.isVirtualThread(writer)) { - Poller.stopPoll(fdVal); - } - if (NativeThread.isNativeThread(reader) - || NativeThread.isNativeThread(writer)) { - nd.preClose(fd); - if (NativeThread.isNativeThread(reader)) - NativeThread.signal(reader); - if (NativeThread.isNativeThread(writer)) - NativeThread.signal(writer); - } - } + nd.preClose(fd, readerThread, writerThread); } } } diff --git a/src/java.base/share/classes/sun/nio/ch/NativeDispatcher.java b/src/java.base/share/classes/sun/nio/ch/NativeDispatcher.java index 1943a3c0569..9b65310784a 100644 --- a/src/java.base/share/classes/sun/nio/ch/NativeDispatcher.java +++ b/src/java.base/share/classes/sun/nio/ch/NativeDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,8 @@ import java.io.FileDescriptor; import java.io.IOException; +import jdk.internal.access.JavaIOFileDescriptorAccess; +import jdk.internal.access.SharedSecrets; /** * Allows different platforms to call different native methods @@ -34,6 +36,7 @@ */ abstract class NativeDispatcher { + private static final JavaIOFileDescriptorAccess JIOFDA = SharedSecrets.getJavaIOFileDescriptorAccess(); abstract int read(FileDescriptor fd, long address, int len) throws IOException; @@ -69,11 +72,28 @@ abstract long writev(FileDescriptor fd, long address, int len) abstract void close(FileDescriptor fd) throws IOException; - // Prepare the given fd for closing by duping it to a known internal fd - // that's already closed. This is necessary on some operating systems - // (Solaris and Linux) to prevent fd recycling. - // - void preClose(FileDescriptor fd) throws IOException { + /** + * Prepare the given file descriptor for closing. If a virtual thread is blocked + * on the file descriptor then it is unparked so that it stops polling. On Unix systems, + * if a platform thread is blocked on the file descriptor then the file descriptor is + * dup'ed to a special fd and the thread signalled so that the syscall fails with EINTR. + */ + final void preClose(FileDescriptor fd, long reader, long writer) throws IOException { + if (NativeThread.isVirtualThread(reader) || NativeThread.isVirtualThread(writer)) { + int fdVal = JIOFDA.get(fd); + Poller.stopPoll(fdVal); + } + if (NativeThread.isNativeThread(reader) || NativeThread.isNativeThread(writer)) { + implPreClose(fd, reader, writer); + } + } + + /** + * This method does nothing by default. On Unix systems the file descriptor is dup'ed + * to a special fd and native threads signalled. + */ + + void implPreClose(FileDescriptor fd, long reader, long writer) throws IOException { // Do nothing by default; this is only needed on Unix } diff --git a/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java b/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java index b9885a36fa8..58cd54fd287 100644 --- a/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -900,20 +900,7 @@ protected void close() throws IOException { // then the socket is pre-closed and the thread(s) signalled. The // last thread will close the file descriptor. if (!tryClose()) { - long reader = readerThread; - long writer = writerThread; - if (NativeThread.isVirtualThread(reader) - || NativeThread.isVirtualThread(writer)) { - Poller.stopPoll(fdVal(fd)); - } - if (NativeThread.isNativeThread(reader) - || NativeThread.isNativeThread(writer)) { - nd.preClose(fd); - if (NativeThread.isNativeThread(reader)) - NativeThread.signal(reader); - if (NativeThread.isNativeThread(writer)) - NativeThread.signal(writer); - } + nd.preClose(fd, readerThread, writerThread); } } } diff --git a/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java index 98ab7a81e3d..0a812229cc9 100644 --- a/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -604,15 +604,7 @@ private void implCloseBlockingMode() throws IOException { assert state < ST_CLOSING; state = ST_CLOSING; if (!tryClose()) { - long th = thread; - if (th != 0) { - if (NativeThread.isVirtualThread(th)) { - Poller.stopPoll(fdVal); - } else { - nd.preClose(fd); - NativeThread.signal(th); - } - } + nd.preClose(fd, thread, 0); } } } diff --git a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java index 996d7e9b7b7..19c0bbe5758 100644 --- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1050,20 +1050,8 @@ private void implCloseBlockingMode() throws IOException { } catch (IOException ignore) { } } - long reader = readerThread; - long writer = writerThread; - if (NativeThread.isVirtualThread(reader) - || NativeThread.isVirtualThread(writer)) { - Poller.stopPoll(fdVal); - } - if (NativeThread.isNativeThread(reader) - || NativeThread.isNativeThread(writer)) { - nd.preClose(fd); - if (NativeThread.isNativeThread(reader)) - NativeThread.signal(reader); - if (NativeThread.isNativeThread(writer)) - NativeThread.signal(writer); - } + // prepare file descriptor for closing + nd.preClose(fd, readerThread, writerThread); } } } diff --git a/src/java.base/unix/classes/sun/nio/ch/DatagramDispatcher.java b/src/java.base/unix/classes/sun/nio/ch/DatagramDispatcher.java index 10a2098a040..8f1692f0e4d 100644 --- a/src/java.base/unix/classes/sun/nio/ch/DatagramDispatcher.java +++ b/src/java.base/unix/classes/sun/nio/ch/DatagramDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,46 +39,43 @@ class DatagramDispatcher extends UnixDispatcher { IOUtil.load(); } + @Override int read(FileDescriptor fd, long address, int len) throws IOException { return read0(fd, address, len); } + @Override long readv(FileDescriptor fd, long address, int len) throws IOException { return readv0(fd, address, len); } + @Override int write(FileDescriptor fd, long address, int len) throws IOException { return write0(fd, address, len); } + @Override long writev(FileDescriptor fd, long address, int len) throws IOException { return writev0(fd, address, len); } - void close(FileDescriptor fd) throws IOException { - close0(fd); - } - - void preClose(FileDescriptor fd) throws IOException { - preClose0(fd); - } - + @Override void dup(FileDescriptor fd1, FileDescriptor fd2) throws IOException { dup0(fd1, fd2); } - static native int read0(FileDescriptor fd, long address, int len) + private static native int read0(FileDescriptor fd, long address, int len) throws IOException; - static native long readv0(FileDescriptor fd, long address, int len) + private static native long readv0(FileDescriptor fd, long address, int len) throws IOException; - static native int write0(FileDescriptor fd, long address, int len) + private static native int write0(FileDescriptor fd, long address, int len) throws IOException; - static native long writev0(FileDescriptor fd, long address, int len) + private static native long writev0(FileDescriptor fd, long address, int len) throws IOException; - static native void dup0(FileDescriptor fd1, FileDescriptor fd2) + private static native void dup0(FileDescriptor fd1, FileDescriptor fd2) throws IOException; } diff --git a/src/java.base/unix/classes/sun/nio/ch/SinkChannelImpl.java b/src/java.base/unix/classes/sun/nio/ch/SinkChannelImpl.java index 7537c1a684f..e53868748c6 100644 --- a/src/java.base/unix/classes/sun/nio/ch/SinkChannelImpl.java +++ b/src/java.base/unix/classes/sun/nio/ch/SinkChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ class SinkChannelImpl implements SelChImpl { // Used to make native read and write calls - private static final NativeDispatcher nd = new FileDispatcherImpl(); + private static final NativeDispatcher nd = new SocketDispatcher(); // The file descriptor associated with this channel private final FileDescriptor fd; @@ -152,15 +152,7 @@ private void implCloseBlockingMode() throws IOException { assert state < ST_CLOSING; state = ST_CLOSING; if (!tryClose()) { - long th = thread; - if (th != 0) { - if (NativeThread.isVirtualThread(th)) { - Poller.stopPoll(fdVal); - } else { - nd.preClose(fd); - NativeThread.signal(th); - } - } + nd.preClose(fd, thread, 0); } } } diff --git a/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java b/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java index 5b262fb58b7..ebc4b2e8fbe 100644 --- a/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java +++ b/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,7 @@ class SocketDispatcher extends UnixDispatcher { * @throws sun.net.ConnectionResetException if connection reset is detected * @throws IOException if another I/O error occurs */ + @Override int read(FileDescriptor fd, long address, int len) throws IOException { return read0(fd, address, len); } @@ -54,26 +55,21 @@ int read(FileDescriptor fd, long address, int len) throws IOException { * @throws sun.net.ConnectionResetException if connection reset is detected * @throws IOException if another I/O error occurs */ + @Override long readv(FileDescriptor fd, long address, int len) throws IOException { return readv0(fd, address, len); } + @Override int write(FileDescriptor fd, long address, int len) throws IOException { return write0(fd, address, len); } + @Override long writev(FileDescriptor fd, long address, int len) throws IOException { return writev0(fd, address, len); } - void close(FileDescriptor fd) throws IOException { - close0(fd); - } - - void preClose(FileDescriptor fd) throws IOException { - preClose0(fd); - } - // -- Native methods -- private static native int read0(FileDescriptor fd, long address, int len) @@ -82,10 +78,10 @@ private static native int read0(FileDescriptor fd, long address, int len) private static native long readv0(FileDescriptor fd, long address, int len) throws IOException; - static native int write0(FileDescriptor fd, long address, int len) + private static native int write0(FileDescriptor fd, long address, int len) throws IOException; - static native long writev0(FileDescriptor fd, long address, int len) + private static native long writev0(FileDescriptor fd, long address, int len) throws IOException; static { diff --git a/src/java.base/unix/classes/sun/nio/ch/SourceChannelImpl.java b/src/java.base/unix/classes/sun/nio/ch/SourceChannelImpl.java index 0ce85ec3b4e..7760118ca02 100644 --- a/src/java.base/unix/classes/sun/nio/ch/SourceChannelImpl.java +++ b/src/java.base/unix/classes/sun/nio/ch/SourceChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ class SourceChannelImpl implements SelChImpl { // Used to make native read and write calls - private static final NativeDispatcher nd = new FileDispatcherImpl(); + private static final NativeDispatcher nd = new SocketDispatcher(); // The file descriptor associated with this channel private final FileDescriptor fd; @@ -152,15 +152,7 @@ private void implCloseBlockingMode() throws IOException { assert state < ST_CLOSING; state = ST_CLOSING; if (!tryClose()) { - long th = thread; - if (th != 0) { - if (NativeThread.isVirtualThread(th)) { - Poller.stopPoll(fdVal); - } else { - nd.preClose(fd); - NativeThread.signal(th); - } - } + nd.preClose(fd, thread, 0); } } } diff --git a/src/java.base/unix/classes/sun/nio/ch/UnixDispatcher.java b/src/java.base/unix/classes/sun/nio/ch/UnixDispatcher.java index bc643100f9d..fcd2d88d7a6 100644 --- a/src/java.base/unix/classes/sun/nio/ch/UnixDispatcher.java +++ b/src/java.base/unix/classes/sun/nio/ch/UnixDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,17 +30,23 @@ abstract class UnixDispatcher extends NativeDispatcher { + @Override void close(FileDescriptor fd) throws IOException { close0(fd); } - void preClose(FileDescriptor fd) throws IOException { + @Override + void implPreClose(FileDescriptor fd, long reader, long writer) throws IOException { preClose0(fd); + if (NativeThread.isNativeThread(reader)) + NativeThread.signal(reader); + if (NativeThread.isNativeThread(writer)) + NativeThread.signal(writer); } - static native void close0(FileDescriptor fd) throws IOException; + private static native void close0(FileDescriptor fd) throws IOException; - static native void preClose0(FileDescriptor fd) throws IOException; + private static native void preClose0(FileDescriptor fd) throws IOException; static native void init(); diff --git a/src/java.base/windows/classes/sun/nio/ch/DatagramDispatcher.java b/src/java.base/windows/classes/sun/nio/ch/DatagramDispatcher.java index c59dfabbced..de40be6cda1 100644 --- a/src/java.base/windows/classes/sun/nio/ch/DatagramDispatcher.java +++ b/src/java.base/windows/classes/sun/nio/ch/DatagramDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,22 +36,27 @@ class DatagramDispatcher extends NativeDispatcher { DatagramDispatcher() { } + @Override int read(FileDescriptor fd, long address, int len) throws IOException { return read0(fd, address, len); } + @Override long readv(FileDescriptor fd, long address, int len) throws IOException { return readv0(fd, address, len); } + @Override int write(FileDescriptor fd, long address, int len) throws IOException { return write0(fd, address, len); } + @Override long writev(FileDescriptor fd, long address, int len) throws IOException { return writev0(fd, address, len); } + @Override void close(FileDescriptor fd) throws IOException { SocketDispatcher.invalidateAndClose(fd); } diff --git a/src/java.base/windows/classes/sun/nio/ch/SocketDispatcher.java b/src/java.base/windows/classes/sun/nio/ch/SocketDispatcher.java index 6ce751bddf7..a9c2a132cad 100644 --- a/src/java.base/windows/classes/sun/nio/ch/SocketDispatcher.java +++ b/src/java.base/windows/classes/sun/nio/ch/SocketDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,26 +42,27 @@ class SocketDispatcher extends NativeDispatcher { SocketDispatcher() { } + @Override int read(FileDescriptor fd, long address, int len) throws IOException { return read0(fd, address, len); } + @Override long readv(FileDescriptor fd, long address, int len) throws IOException { return readv0(fd, address, len); } + @Override int write(FileDescriptor fd, long address, int len) throws IOException { return write0(fd, address, len); } + @Override long writev(FileDescriptor fd, long address, int len) throws IOException { return writev0(fd, address, len); } - void preClose(FileDescriptor fd) throws IOException { - throw new UnsupportedOperationException(); - } - + @Override void close(FileDescriptor fd) throws IOException { invalidateAndClose(fd); }