7012768: InetAddress lookupTable leaks/deadlocks when using unsupported name service spi
Reviewed-by: alanb, michaelm
diff --git a/jdk/src/share/classes/java/net/InetAddress.java b/jdk/src/share/classes/java/net/InetAddress.java
index 889cc6d..926ef86 100644
--- a/jdk/src/share/classes/java/net/InetAddress.java
+++ b/jdk/src/share/classes/java/net/InetAddress.java
@@ -677,8 +677,7 @@
static InetAddressImpl impl;
- private static HashMap<String, InetAddress[]> lookupTable
- = new HashMap<String, InetAddress[]>();
+ private static final HashMap<String, Void> lookupTable = new HashMap<>();
/**
* Represents a cache entry
@@ -737,7 +736,7 @@
// As we iterate in insertion order we can
// terminate when a non-expired entry is found.
- LinkedList<String> expired = new LinkedList<String>();
+ LinkedList<String> expired = new LinkedList<>();
long now = System.currentTimeMillis();
for (String key : cache.keySet()) {
CacheEntry entry = cache.get(key);
@@ -1227,43 +1226,45 @@
// lookupTable and return null so the
// following code would do a lookup itself.
if ((addresses = checkLookupTable(host)) == null) {
- // This is the first thread which looks up the addresses
- // this host or the cache entry for this host has been
- // expired so this thread should do the lookup.
- for (NameService nameService : nameServices) {
- try {
- /*
- * Do not put the call to lookup() inside the
- * constructor. if you do you will still be
- * allocating space when the lookup fails.
- */
+ try {
+ // This is the first thread which looks up the addresses
+ // this host or the cache entry for this host has been
+ // expired so this thread should do the lookup.
+ for (NameService nameService : nameServices) {
+ try {
+ /*
+ * Do not put the call to lookup() inside the
+ * constructor. if you do you will still be
+ * allocating space when the lookup fails.
+ */
- addresses = nameService.lookupAllHostAddr(host);
- success = true;
- break;
- } catch (UnknownHostException uhe) {
- if (host.equalsIgnoreCase("localhost")) {
- InetAddress[] local = new InetAddress[] { impl.loopbackAddress() };
- addresses = local;
+ addresses = nameService.lookupAllHostAddr(host);
success = true;
break;
- }
- else {
- addresses = unknown_array;
- success = false;
- ex = uhe;
+ } catch (UnknownHostException uhe) {
+ if (host.equalsIgnoreCase("localhost")) {
+ InetAddress[] local = new InetAddress[] { impl.loopbackAddress() };
+ addresses = local;
+ success = true;
+ break;
+ }
+ else {
+ addresses = unknown_array;
+ success = false;
+ ex = uhe;
+ }
}
}
- }
- // Cache the addresses.
- cacheAddresses(host, addresses, success);
- // Delete the host from the lookupTable, and
- // notify all threads waiting for the monitor
- // for lookupTable.
- updateLookupTable(host);
- if (!success && ex != null)
- throw ex;
+ // Cache the addresses.
+ cacheAddresses(host, addresses, success);
+ if (!success && ex != null)
+ throw ex;
+ } finally {
+ // Delete host from the lookupTable and notify
+ // all threads waiting on the lookupTable monitor.
+ updateLookupTable(host);
+ }
}
return addresses;
@@ -1271,16 +1272,13 @@
private static InetAddress[] checkLookupTable(String host) {
- // make sure addresses is null.
- InetAddress[] addresses = null;
-
synchronized (lookupTable) {
// If the host isn't in the lookupTable, add it in the
// lookuptable and return null. The caller should do
// the lookup.
if (lookupTable.containsKey(host) == false) {
lookupTable.put(host, null);
- return addresses;
+ return null;
}
// If the host is in the lookupTable, it means that another
@@ -1298,10 +1296,11 @@
// the host. This thread should retry to get the addresses
// from the addressCache. If it doesn't get the addresses from
// the cache, it will try to look up the addresses itself.
- addresses = getCachedAddresses(host);
+ InetAddress[] addresses = getCachedAddresses(host);
if (addresses == null) {
synchronized (lookupTable) {
lookupTable.put(host, null);
+ return null;
}
}
diff --git a/jdk/test/java/net/InetAddress/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor b/jdk/test/java/net/InetAddress/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
deleted file mode 100644
index efcf237..0000000
--- a/jdk/test/java/net/InetAddress/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
+++ /dev/null
@@ -1,2 +0,0 @@
-Simple1NameServiceDescriptor
-Simple2NameServiceDescriptor
diff --git a/jdk/test/sun/net/InetAddress/nameservice/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor b/jdk/test/sun/net/InetAddress/nameservice/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
deleted file mode 100644
index 6fc851d..0000000
--- a/jdk/test/sun/net/InetAddress/nameservice/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
+++ /dev/null
@@ -1,2 +0,0 @@
-# name service provider descriptor
-SimpleNameServiceDescriptor
diff --git a/jdk/test/sun/net/InetAddress/nameservice/chaining/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor b/jdk/test/sun/net/InetAddress/nameservice/chaining/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
new file mode 100644
index 0000000..5ed3b8e
--- /dev/null
+++ b/jdk/test/sun/net/InetAddress/nameservice/chaining/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
@@ -0,0 +1,23 @@
+# Copyright (c) 2011, 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
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions
+
+Simple1NameServiceDescriptor
+Simple2NameServiceDescriptor
diff --git a/jdk/test/java/net/InetAddress/B4762344.java b/jdk/test/sun/net/InetAddress/nameservice/chaining/Providers.java
similarity index 90%
rename from jdk/test/java/net/InetAddress/B4762344.java
rename to jdk/test/sun/net/InetAddress/nameservice/chaining/Providers.java
index 0e28705..590f4e2 100644
--- a/jdk/test/java/net/InetAddress/B4762344.java
+++ b/jdk/test/sun/net/InetAddress/nameservice/chaining/Providers.java
@@ -25,15 +25,17 @@
* @test
* @bug 4762344
* @summary 2nd nameservice provider is non functional
- * @build B4762344 SimpleNameService Simple1NameServiceDescriptor Simple2NameServiceDescriptor
- * @run main/othervm -Dsun.net.spi.nameservice.provider.1=simple1,sun -Dsun.net.spi.nameservice.provider.2=simple2,sun B4762344
+ * @compile -XDignore.symbol.file=true SimpleNameService.java
+ * Simple1NameServiceDescriptor.java
+ * Simple2NameServiceDescriptor.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=simple1,sun -Dsun.net.spi.nameservice.provider.2=simple2,sun Providers
*/
import java.net.*;
import java.util.*;
-public class B4762344 {
+public class Providers {
private static String[][] hostnames = new String[][] {
// both providers know this host, but with different address
new String[] {"blade", "10.0.0.1"},
diff --git a/jdk/test/java/net/InetAddress/Simple1NameServiceDescriptor.java b/jdk/test/sun/net/InetAddress/nameservice/chaining/Simple1NameServiceDescriptor.java
similarity index 100%
rename from jdk/test/java/net/InetAddress/Simple1NameServiceDescriptor.java
rename to jdk/test/sun/net/InetAddress/nameservice/chaining/Simple1NameServiceDescriptor.java
diff --git a/jdk/test/java/net/InetAddress/Simple2NameServiceDescriptor.java b/jdk/test/sun/net/InetAddress/nameservice/chaining/Simple2NameServiceDescriptor.java
similarity index 100%
rename from jdk/test/java/net/InetAddress/Simple2NameServiceDescriptor.java
rename to jdk/test/sun/net/InetAddress/nameservice/chaining/Simple2NameServiceDescriptor.java
diff --git a/jdk/test/java/net/InetAddress/SimpleNameService.java b/jdk/test/sun/net/InetAddress/nameservice/chaining/SimpleNameService.java
similarity index 100%
rename from jdk/test/java/net/InetAddress/SimpleNameService.java
rename to jdk/test/sun/net/InetAddress/nameservice/chaining/SimpleNameService.java
diff --git a/jdk/test/sun/net/InetAddress/nameservice/deadlock/Hang.java b/jdk/test/sun/net/InetAddress/nameservice/deadlock/Hang.java
new file mode 100644
index 0000000..79246ea
--- /dev/null
+++ b/jdk/test/sun/net/InetAddress/nameservice/deadlock/Hang.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 7012768
+ * @compile -XDignore.symbol.file=true ThrowingNameService.java
+ * ThrowingNameServiceDescriptor.java
+ * @run main/othervm/timeout=30 -Dsun.net.spi.nameservice.provider.1=throwing,sun Hang
+ * @summary InetAddress lookupTable leaks/deadlocks when using unsupported
+ * name service spi
+ */
+
+import java.net.InetAddress;
+
+public class Hang {
+ public static void main(String[] args) throws Exception {
+ try {
+ // 1st attempt - IllegalStateException caught below
+ InetAddress.getByName("host.company.com");
+ } catch (IllegalStateException e) { }
+
+ // 2nd attempt - Stuck here forever if bug exists
+ InetAddress.getByName("host.company.com");
+ }
+}
diff --git a/jdk/test/sun/net/InetAddress/nameservice/deadlock/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor b/jdk/test/sun/net/InetAddress/nameservice/deadlock/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
new file mode 100644
index 0000000..3490a90
--- /dev/null
+++ b/jdk/test/sun/net/InetAddress/nameservice/deadlock/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
@@ -0,0 +1,22 @@
+# Copyright (c) 2011, 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
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+
+ThrowingNameServiceDescriptor
diff --git a/jdk/test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameService.java b/jdk/test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameService.java
new file mode 100644
index 0000000..292b31d
--- /dev/null
+++ b/jdk/test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameService.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2011, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import sun.net.spi.nameservice.NameService;
+
+public class ThrowingNameService implements NameService {
+ static boolean firstCall = true;
+
+ @Override
+ public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException {
+ if (firstCall) {
+ firstCall = false;
+ // throw unchecked exception first time round
+ throw new IllegalStateException();
+ }
+
+ // return any valid address
+ return new InetAddress[] { InetAddress.getLoopbackAddress() };
+ }
+
+ @Override
+ public String getHostByAddr(byte[] addr) throws UnknownHostException {
+ throw new IllegalStateException();
+ }
+}
diff --git a/jdk/test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameServiceDescriptor.java b/jdk/test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameServiceDescriptor.java
new file mode 100644
index 0000000..3075412
--- /dev/null
+++ b/jdk/test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameServiceDescriptor.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2011, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import sun.net.spi.nameservice.*;
+
+public class ThrowingNameServiceDescriptor implements NameServiceDescriptor {
+ public NameService createNameService() {
+ return new ThrowingNameService();
+ }
+
+ @Override
+ public String getProviderName() {
+ return "sun";
+ }
+
+ @Override
+ public String getType() {
+ return "throwing";
+ }
+}
diff --git a/jdk/test/sun/net/InetAddress/nameservice/CacheTest.java b/jdk/test/sun/net/InetAddress/nameservice/simple/CacheTest.java
similarity index 96%
rename from jdk/test/sun/net/InetAddress/nameservice/CacheTest.java
rename to jdk/test/sun/net/InetAddress/nameservice/simple/CacheTest.java
index b6bf0e1..0aadfd3 100644
--- a/jdk/test/sun/net/InetAddress/nameservice/CacheTest.java
+++ b/jdk/test/sun/net/InetAddress/nameservice/simple/CacheTest.java
@@ -26,8 +26,8 @@
* @summary Check that InetAddress doesn't continue to throw UHE
* after the name service has recovered and the negative ttl
* on the initial lookup has expired.
- *
- * @build CacheTest SimpleNameService SimpleNameServiceDescriptor
+ * @compile -XDignore.symbol.file=true SimpleNameService.java
+ * SimpleNameServiceDescriptor.java
* @run main/othervm/timeout=200 -Dsun.net.spi.nameservice.provider.1=simple,sun CacheTest
*/
import java.net.InetAddress;
diff --git a/jdk/test/sun/net/InetAddress/nameservice/B6442088.java b/jdk/test/sun/net/InetAddress/nameservice/simple/DefaultCaching.java
similarity index 94%
rename from jdk/test/sun/net/InetAddress/nameservice/B6442088.java
rename to jdk/test/sun/net/InetAddress/nameservice/simple/DefaultCaching.java
index a68f798..f1010da 100644
--- a/jdk/test/sun/net/InetAddress/nameservice/B6442088.java
+++ b/jdk/test/sun/net/InetAddress/nameservice/simple/DefaultCaching.java
@@ -25,15 +25,15 @@
* @bug 6442088
* @summary Change default DNS caching behavior for code not running under
* security manager.
- *
- * @build B6442088 SimpleNameService SimpleNameServiceDescriptor
- * @run main/othervm/timeout=200 -Dsun.net.inetaddr.ttl=20 -Dsun.net.spi.nameservice.provider.1=simple,sun B6442088
+ * @compile -XDignore.symbol.file=true SimpleNameService.java
+ * SimpleNameServiceDescriptor.java
+ * @run main/othervm/timeout=200 -Dsun.net.inetaddr.ttl=20 -Dsun.net.spi.nameservice.provider.1=simple,sun DefaultCaching
*/
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.Security;
-public class B6442088 {
+public class DefaultCaching {
public static void main(String args[]) throws Exception {
diff --git a/jdk/test/sun/net/InetAddress/nameservice/simple/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor b/jdk/test/sun/net/InetAddress/nameservice/simple/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
new file mode 100644
index 0000000..b7527c07
--- /dev/null
+++ b/jdk/test/sun/net/InetAddress/nameservice/simple/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
@@ -0,0 +1,22 @@
+# Copyright (c) 2011, 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
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+
+SimpleNameServiceDescriptor # name service provider descriptor
diff --git a/jdk/test/sun/net/InetAddress/nameservice/SimpleNameService.java b/jdk/test/sun/net/InetAddress/nameservice/simple/SimpleNameService.java
similarity index 100%
rename from jdk/test/sun/net/InetAddress/nameservice/SimpleNameService.java
rename to jdk/test/sun/net/InetAddress/nameservice/simple/SimpleNameService.java
diff --git a/jdk/test/sun/net/InetAddress/nameservice/SimpleNameServiceDescriptor.java b/jdk/test/sun/net/InetAddress/nameservice/simple/SimpleNameServiceDescriptor.java
similarity index 100%
rename from jdk/test/sun/net/InetAddress/nameservice/SimpleNameServiceDescriptor.java
rename to jdk/test/sun/net/InetAddress/nameservice/simple/SimpleNameServiceDescriptor.java