src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java
changeset 58808 9261ad32cba9
parent 58518 705c3f88a409
child 58899 5573a7098439
--- a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Fri Oct 25 13:17:31 2019 -0700
+++ b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Sun Oct 27 12:13:51 2019 +0000
@@ -27,6 +27,8 @@
 
 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.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 @@
     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 @@
     // 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 @@
             ResourceManager.afterUdpClose();
             throw ioe;
         }
+        this.cleaner = CleanerFactory.cleaner().register(this, closerFor(fd));
     }
 
     public DatagramChannelImpl(SelectorProvider sp, ProtocolFamily family)
@@ -164,6 +169,7 @@
             ResourceManager.afterUdpClose();
             throw ioe;
         }
+        this.cleaner = CleanerFactory.cleaner().register(this, closerFor(fd));
     }
 
     public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd)
@@ -179,6 +185,7 @@
                 : 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 @@
         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 @@
         }
     }
 
-    @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 @@
         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 --