changeset 49720:acdb8531cc8b

8199215: Re-examine getFreePort method in test infrastructure library Reviewed-by: alanb
author mli
date Fri, 16 Mar 2018 18:15:31 +0800
parents 422615764e12
children ca2780cd2056
files test/jdk/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java test/jdk/java/nio/channels/DatagramChannel/IsBound.java test/jdk/java/nio/channels/DatagramChannel/IsConnected.java test/jdk/java/nio/channels/Selector/Alias.java test/jdk/java/nio/channels/Selector/BasicConnect.java test/jdk/java/nio/channels/Selector/Connect.java test/jdk/java/nio/channels/Selector/ConnectWrite.java test/jdk/java/nio/channels/Selector/KeysReady.java test/jdk/java/nio/channels/SocketChannel/AdaptSocket.java test/jdk/java/nio/channels/SocketChannel/Basic.java test/jdk/java/nio/channels/SocketChannel/CloseDuringConnect.java test/jdk/java/nio/channels/SocketChannel/Connect.java test/jdk/java/nio/channels/SocketChannel/ConnectState.java test/jdk/java/nio/channels/SocketChannel/FinishConnect.java test/jdk/java/nio/channels/SocketChannel/IsConnectable.java test/jdk/java/nio/channels/SocketChannel/LocalAddress.java test/jdk/java/nio/channels/SocketChannel/Stream.java test/jdk/java/nio/channels/SocketChannel/VectorParams.java test/jdk/java/nio/channels/TestServers.java test/jdk/lib/testlibrary/jdk/testlibrary/Utils.java test/lib/jdk/test/lib/Utils.java
diffstat 21 files changed, 112 insertions(+), 97 deletions(-) [+]
line wrap: on
line diff
--- a/test/jdk/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -24,7 +24,9 @@
 /* @test
  * @bug 4313882 4981129 8143610
  * @summary Unit test for datagram-socket-channel adaptors
- * @library ..
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @run main AdaptDatagramSocket
  * @key randomness
  */
 
--- a/test/jdk/java/nio/channels/DatagramChannel/IsBound.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/DatagramChannel/IsBound.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -24,7 +24,9 @@
 /* @test
  * @bug 4468875
  * @summary Simple test of DatagramChannel isBound
- * @library ..
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @run main IsBound
  */
 
 import java.net.*;
--- a/test/jdk/java/nio/channels/DatagramChannel/IsConnected.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/DatagramChannel/IsConnected.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -24,7 +24,9 @@
 /* @test
  * @bug 4446035
  * @summary Simple test of DatagramSocket connection consistency
- * @library ..
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @run main IsConnected
  */
 
 import java.net.*;
--- a/test/jdk/java/nio/channels/Selector/Alias.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/Selector/Alias.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -24,7 +24,9 @@
 /* @test
  * @bug 4513011
  * @summary Registering and cancelling same fd many times
- * @library ..
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @run main Alias
  */
 
 import java.net.*;
--- a/test/jdk/java/nio/channels/Selector/BasicConnect.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/Selector/BasicConnect.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -24,7 +24,9 @@
 /* @test
  * @summary Test nonblocking connect and finishConnect
  * @bug 4457776
- * @library ..
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @run main BasicConnect
  */
 
 import java.net.*;
--- a/test/jdk/java/nio/channels/Selector/Connect.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/Selector/Connect.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -24,7 +24,9 @@
 /* @test
  * @bug 4511624
  * @summary Test Making lots of Selectors
- * @library ..
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @run main Connect
  */
 
 import java.net.*;
--- a/test/jdk/java/nio/channels/Selector/ConnectWrite.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/Selector/ConnectWrite.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, 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
@@ -24,7 +24,9 @@
 /* @test
  * @bug 4505829
  * @summary Test ready for connect followed by ready for write
- * @library ..
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @run main ConnectWrite
  */
 
 import java.net.*;
--- a/test/jdk/java/nio/channels/Selector/KeysReady.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/Selector/KeysReady.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, 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
@@ -24,7 +24,9 @@
 /* @test
  * @bug 4530007
  * @summary Test if keys reported ready multiple times
- * @library ..
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @run main KeysReady
  */
 
 import java.net.*;
--- a/test/jdk/java/nio/channels/SocketChannel/AdaptSocket.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/SocketChannel/AdaptSocket.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -24,7 +24,9 @@
 /* @test
  * @bug 8156002
  * @summary Unit test for socket-channel adaptors
- * @library ..
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @run main AdaptSocket
  */
 
 import java.io.*;
--- a/test/jdk/java/nio/channels/SocketChannel/Basic.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/SocketChannel/Basic.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -23,7 +23,9 @@
 
 /* @test
  * @summary Unit test for socket channels
- * @library ..
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @run main Basic
  */
 
 import java.net.*;
--- a/test/jdk/java/nio/channels/SocketChannel/CloseDuringConnect.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/SocketChannel/CloseDuringConnect.java	Fri Mar 16 18:15:31 2018 +0800
@@ -23,6 +23,8 @@
 
 /* @test
  * @bug 8198928
+ * @library /test/lib
+ * @build jdk.test.lib.Utils
  * @run main CloseDuringConnect
  * @summary Attempt to cause a deadlock by closing a SocketChannel in one thread
  *     where another thread is closing the channel after a connect fail
@@ -40,6 +42,8 @@
 import java.util.stream.IntStream;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
+import jdk.test.lib.Utils;
+
 public class CloseDuringConnect {
 
     // number of test iterations, needs to be 5-10 at least
@@ -49,26 +53,6 @@
     static final int MAX_DELAY_BEFORE_CLOSE = 20;
 
     /**
-     * Returns the socket address of an endpoint that refuses connections. The
-     * endpoint is an InetSocketAddress where the address is the loopback address
-     * and the port is a system port (1-1023 range).
-     */
-    static SocketAddress refusingEndpoint() {
-        InetAddress lb = InetAddress.getLoopbackAddress();
-        int port = 1;
-        while (port < 1024) {
-            SocketAddress sa = new InetSocketAddress(lb, port);
-            try {
-                SocketChannel.open(sa).close();
-            } catch (IOException ioe) {
-                return sa;
-            }
-            port++;
-        }
-        throw new RuntimeException("Unable to find system port that is refusing connections");
-    }
-
-    /**
      * Invoked by a task in the thread pool to connect to a remote address.
      * The connection should never be established.
      */
@@ -123,7 +107,7 @@
     }
 
     public static void main(String[] args) throws Exception {
-        SocketAddress refusing = refusingEndpoint();
+        SocketAddress refusing = Utils.refusingEndpoint();
         ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
         try {
             IntStream.range(0, ITERATIONS).forEach(i -> {
--- a/test/jdk/java/nio/channels/SocketChannel/Connect.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/SocketChannel/Connect.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, 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
@@ -24,7 +24,9 @@
 /* @test
  * @bug 4650679 8037360
  * @summary Unit test for socket channels
- * @library ..
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @run main Connect
  */
 
 import java.net.*;
--- a/test/jdk/java/nio/channels/SocketChannel/ConnectState.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/SocketChannel/ConnectState.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -23,7 +23,9 @@
 
 /* @test
  * @summary Test socket-channel connection-state transitions
- * @library ..
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @run main ConnectState
  */
 
 import java.io.*;
--- a/test/jdk/java/nio/channels/SocketChannel/FinishConnect.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/SocketChannel/FinishConnect.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -23,7 +23,9 @@
 
 /* @test
  * @summary Test SocketChannel.finishConnect
- * @library ..
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @run main FinishConnect
  */
 
 import java.net.*;
--- a/test/jdk/java/nio/channels/SocketChannel/IsConnectable.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/SocketChannel/IsConnectable.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, 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
@@ -24,7 +24,9 @@
 /* @test
  * @bug 4737146 4750573
  * @summary Test if isConnectable returns true after connected
- * @library ..
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @run main IsConnectable
  */
 
 import java.net.*;
--- a/test/jdk/java/nio/channels/SocketChannel/LocalAddress.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/SocketChannel/LocalAddress.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, 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
@@ -24,7 +24,9 @@
 /* @test
  * @bug 4672609 5076965 4739238
  * @summary Test getLocalAddress getLocalPort
- * @library ..
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @run main LocalAddress
  */
 
 import java.net.*;
--- a/test/jdk/java/nio/channels/SocketChannel/Stream.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/SocketChannel/Stream.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -24,7 +24,9 @@
 /* @test
  * @bug 4430139
  * @summary Test result of read on stream from nonblocking channel
- * @library ..
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @run main Stream
  */
 
 import java.io.*;
--- a/test/jdk/java/nio/channels/SocketChannel/VectorParams.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/SocketChannel/VectorParams.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -24,7 +24,9 @@
 /* @test
  * @bug 4865031
  * @summary Test ScatteringByteChannel/GatheringByteChannel read/write
- * @library ..
+ * @library .. /test/lib
+ * @build jdk.test.lib.Utils TestServers
+ * @run main VectorParams
  */
 
 import java.io.*;
--- a/test/jdk/java/nio/channels/TestServers.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/java/nio/channels/TestServers.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, 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
@@ -31,6 +31,8 @@
 import java.util.Date;
 import java.util.List;
 
+import jdk.test.lib.Utils;
+
 
 public class TestServers {
 
@@ -81,11 +83,8 @@
         }
 
         public static RefusingServer newRefusingServer() throws IOException {
-            // The port 1 is reserved for TCPMUX(RFC 1078), which is seldom used,
-            // and it's not used on all the test platform through JPRT.
-            // So we choose to use it as a refusing "server"'s "listen" port,
-            // it's much more stable than "open->close a server socket".
-            return new RefusingServer(InetAddress.getLocalHost(), 1);
+            return new RefusingServer(InetAddress.getLocalHost(),
+                       Utils.refusingEndpoint().getPort());
         }
     }
 
--- a/test/jdk/lib/testlibrary/jdk/testlibrary/Utils.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/jdk/lib/testlibrary/jdk/testlibrary/Utils.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -176,28 +176,15 @@
 
     /**
      * Returns the free port on the local host.
-     * The function will spin until a valid port number is found.
      *
      * @return The port number
-     * @throws InterruptedException if any thread has interrupted the current thread
      * @throws IOException if an I/O error occurs when opening the socket
      */
-    public static int getFreePort() throws InterruptedException, IOException {
-        int port = -1;
-
-        while (port <= 0) {
-            Thread.sleep(100);
-
-            ServerSocket serverSocket = null;
-            try {
-                serverSocket = new ServerSocket(0);
-                port = serverSocket.getLocalPort();
-            } finally {
-                serverSocket.close();
-            }
+    public static int getFreePort() throws IOException {
+        try (ServerSocket serverSocket =
+                new ServerSocket(0, 5, InetAddress.getLoopbackAddress());) {
+            return serverSocket.getLocalPort();
         }
-
-        return port;
     }
 
     /**
--- a/test/lib/jdk/test/lib/Utils.java	Thu Mar 15 14:54:10 2018 -0700
+++ b/test/lib/jdk/test/lib/Utils.java	Fri Mar 16 18:15:31 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -26,6 +26,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.net.InetAddress;
+import java.net.InetSocketAddress;
 import java.net.MalformedURLException;
 import java.net.ServerSocket;
 import java.net.URL;
@@ -34,6 +35,7 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.nio.channels.SocketChannel;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -260,29 +262,38 @@
     }
 
     /**
+     * Returns the socket address of an endpoint that refuses connections. The
+     * endpoint is an InetSocketAddress where the address is the loopback address
+     * and the port is a system port (1-1023 range).
+     * This method is a better choice than getFreePort for tests that need
+     * an endpoint that refuses connections.
+     */
+    public static InetSocketAddress refusingEndpoint() {
+        InetAddress lb = InetAddress.getLoopbackAddress();
+        int port = 1;
+        while (port < 1024) {
+            InetSocketAddress sa = new InetSocketAddress(lb, port);
+            try {
+                SocketChannel.open(sa).close();
+            } catch (IOException ioe) {
+                return sa;
+            }
+            port++;
+        }
+        throw new RuntimeException("Unable to find system port that is refusing connections");
+    }
+
+    /**
      * Returns the free port on the local host.
-     * The function will spin until a valid port number is found.
      *
      * @return The port number
-     * @throws InterruptedException if any thread has interrupted the current thread
      * @throws IOException if an I/O error occurs when opening the socket
      */
-    public static int getFreePort() throws InterruptedException, IOException {
-        int port = -1;
-
-        while (port <= 0) {
-            Thread.sleep(100);
-
-            ServerSocket serverSocket = null;
-            try {
-                serverSocket = new ServerSocket(0);
-                port = serverSocket.getLocalPort();
-            } finally {
-                serverSocket.close();
-            }
+    public static int getFreePort() throws IOException {
+        try (ServerSocket serverSocket =
+                new ServerSocket(0, 5, InetAddress.getLoopbackAddress());) {
+            return serverSocket.getLocalPort();
         }
-
-        return port;
     }
 
     /**