8212132: (dc) Remove DatagramChannelImpl finalize method

Reviewed-by: bpb, chegar, dfuchs, martin
This commit is contained in:
Alan Bateman 2019-10-27 12:13:51 +00:00
parent a2844b54e1
commit 0290476112
3 changed files with 219 additions and 58 deletions

View file

@ -27,6 +27,8 @@ package sun.nio.ch;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.ref.Cleaner.Cleanable;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.Inet6Address;
@ -55,6 +57,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
import jdk.internal.ref.CleanerFactory;
import sun.net.ResourceManager;
import sun.net.ext.ExtendedSocketOptions;
import sun.net.util.IPAddressUtil;
@ -68,7 +71,7 @@ class DatagramChannelImpl
implements SelChImpl
{
// Used to make native read and write calls
private static NativeDispatcher nd = new DatagramDispatcher();
private static final NativeDispatcher nd = new DatagramDispatcher();
// The protocol family of the socket
private final ProtocolFamily family;
@ -76,6 +79,7 @@ class DatagramChannelImpl
// Our file descriptor
private final FileDescriptor fd;
private final int fdVal;
private final Cleanable cleaner;
// Cached InetAddress and port for unconnected DatagramChannels
// used by receive0
@ -138,6 +142,7 @@ class DatagramChannelImpl
ResourceManager.afterUdpClose();
throw ioe;
}
this.cleaner = CleanerFactory.cleaner().register(this, closerFor(fd));
}
public DatagramChannelImpl(SelectorProvider sp, ProtocolFamily family)
@ -164,6 +169,7 @@ class DatagramChannelImpl
ResourceManager.afterUdpClose();
throw ioe;
}
this.cleaner = CleanerFactory.cleaner().register(this, closerFor(fd));
}
public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd)
@ -179,6 +185,7 @@ class DatagramChannelImpl
: StandardProtocolFamily.INET;
this.fd = fd;
this.fdVal = IOUtil.fdVal(fd);
this.cleaner = CleanerFactory.cleaner().register(this, closerFor(fd));
synchronized (stateLock) {
this.localAddress = Net.localAddress(fd);
}
@ -1181,10 +1188,10 @@ class DatagramChannelImpl
if ((readerThread == 0) && (writerThread == 0) && !isRegistered()) {
state = ST_CLOSED;
try {
nd.close(fd);
} finally {
// notify resource manager
ResourceManager.afterUdpClose();
// close socket
cleaner.clean();
} catch (UncheckedIOException ioe) {
throw ioe.getCause();
}
return true;
} else {
@ -1283,13 +1290,6 @@ class DatagramChannelImpl
}
}
@SuppressWarnings("deprecation")
protected void finalize() throws IOException {
// fd is null if constructor threw exception
if (fd != null)
close();
}
/**
* Translates native poll revent set into a ready operation set
*/
@ -1377,6 +1377,21 @@ class DatagramChannelImpl
return fdVal;
}
/**
* Returns an action to close the given file descriptor.
*/
private static Runnable closerFor(FileDescriptor fd) {
return () -> {
try {
nd.close(fd);
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
} finally {
// decrement
ResourceManager.afterUdpClose();
}
};
}
// -- Native methods --

View file

@ -30,8 +30,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.lang.ref.Cleaner.Cleanable;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ProtocolFamily;
@ -106,7 +105,7 @@ public final class NioSocketImpl extends SocketImpl implements PlatformSocketImp
// set by SocketImpl.create, protected by stateLock
private boolean stream;
private FileDescriptorCloser closer;
private Cleanable cleaner;
// set to true when the socket is in non-blocking mode
private volatile boolean nonBlocking;
@ -471,9 +470,10 @@ public final class NioSocketImpl extends SocketImpl implements PlatformSocketImp
ResourceManager.afterUdpClose();
throw ioe;
}
Runnable closer = closerFor(fd, stream);
this.fd = fd;
this.stream = stream;
this.closer = FileDescriptorCloser.create(this);
this.cleaner = CleanerFactory.cleaner().register(this, closer);
this.state = ST_UNCONNECTED;
}
}
@ -777,10 +777,11 @@ public final class NioSocketImpl extends SocketImpl implements PlatformSocketImp
}
// set the fields
Runnable closer = closerFor(newfd, true);
synchronized (nsi.stateLock) {
nsi.fd = newfd;
nsi.stream = true;
nsi.closer = FileDescriptorCloser.create(nsi);
nsi.cleaner = CleanerFactory.cleaner().register(nsi, closer);
nsi.localport = localAddress.getPort();
nsi.address = isaa[0].getAddress();
nsi.port = isaa[0].getPort();
@ -850,7 +851,7 @@ public final class NioSocketImpl extends SocketImpl implements PlatformSocketImp
assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
if (readerThread == 0 && writerThread == 0) {
try {
closer.run();
cleaner.clean();
} catch (UncheckedIOException ioe) {
throw ioe.getCause();
} finally {
@ -1193,53 +1194,28 @@ public final class NioSocketImpl extends SocketImpl implements PlatformSocketImp
}
/**
* A task that closes a SocketImpl's file descriptor. The task runs when the
* SocketImpl is explicitly closed and when the SocketImpl becomes phantom
* reachable.
* Returns an action to close the given file descriptor.
*/
private static class FileDescriptorCloser implements Runnable {
private static final VarHandle CLOSED;
static {
try {
MethodHandles.Lookup l = MethodHandles.lookup();
CLOSED = l.findVarHandle(FileDescriptorCloser.class,
"closed",
boolean.class);
} catch (Exception e) {
throw new InternalError(e);
}
}
private final FileDescriptor fd;
private final boolean stream;
private volatile boolean closed;
FileDescriptorCloser(FileDescriptor fd, boolean stream) {
this.fd = fd;
this.stream = stream;
}
static FileDescriptorCloser create(NioSocketImpl impl) {
assert Thread.holdsLock(impl.stateLock);
var closer = new FileDescriptorCloser(impl.fd, impl.stream);
CleanerFactory.cleaner().register(impl, closer);
return closer;
}
@Override
public void run() {
if (CLOSED.compareAndSet(this, false, true)) {
private static Runnable closerFor(FileDescriptor fd, boolean stream) {
if (stream) {
return () -> {
try {
nd.close(fd);
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
}
};
} else {
return () -> {
try {
nd.close(fd);
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
} finally {
if (!stream) {
// decrement
ResourceManager.afterUdpClose();
}
// decrement
ResourceManager.afterUdpClose();
}
}
};
}
}