jdk/src/share/classes/java/net/InetAddress.java
changeset 7995 8168047d48c2
parent 7668 d4a77089c587
child 9035 1255eb81cc2f
equal deleted inserted replaced
7993:8778b8786a81 7995:8168047d48c2
   675 
   675 
   676     static InetAddress[]    unknown_array; // put THIS in cache
   676     static InetAddress[]    unknown_array; // put THIS in cache
   677 
   677 
   678     static InetAddressImpl  impl;
   678     static InetAddressImpl  impl;
   679 
   679 
   680     private static HashMap<String, InetAddress[]> lookupTable
   680     private static final HashMap<String, Void> lookupTable = new HashMap<>();
   681         = new HashMap<String, InetAddress[]>();
       
   682 
   681 
   683     /**
   682     /**
   684      * Represents a cache entry
   683      * Represents a cache entry
   685      */
   684      */
   686     static final class CacheEntry {
   685     static final class CacheEntry {
   735 
   734 
   736             if (policy != InetAddressCachePolicy.FOREVER) {
   735             if (policy != InetAddressCachePolicy.FOREVER) {
   737 
   736 
   738                 // As we iterate in insertion order we can
   737                 // As we iterate in insertion order we can
   739                 // terminate when a non-expired entry is found.
   738                 // terminate when a non-expired entry is found.
   740                 LinkedList<String> expired = new LinkedList<String>();
   739                 LinkedList<String> expired = new LinkedList<>();
   741                 long now = System.currentTimeMillis();
   740                 long now = System.currentTimeMillis();
   742                 for (String key : cache.keySet()) {
   741                 for (String key : cache.keySet()) {
   743                     CacheEntry entry = cache.get(key);
   742                     CacheEntry entry = cache.get(key);
   744 
   743 
   745                     if (entry.expiration >= 0 && entry.expiration < now) {
   744                     if (entry.expiration >= 0 && entry.expiration < now) {
  1225         //         addressCache for any reason,
  1224         //         addressCache for any reason,
  1226         //         it should add the host in the
  1225         //         it should add the host in the
  1227         //         lookupTable and return null so the
  1226         //         lookupTable and return null so the
  1228         //         following code would do  a lookup itself.
  1227         //         following code would do  a lookup itself.
  1229         if ((addresses = checkLookupTable(host)) == null) {
  1228         if ((addresses = checkLookupTable(host)) == null) {
  1230             // This is the first thread which looks up the addresses
  1229             try {
  1231             // this host or the cache entry for this host has been
  1230                 // This is the first thread which looks up the addresses
  1232             // expired so this thread should do the lookup.
  1231                 // this host or the cache entry for this host has been
  1233             for (NameService nameService : nameServices) {
  1232                 // expired so this thread should do the lookup.
  1234                 try {
  1233                 for (NameService nameService : nameServices) {
  1235                     /*
  1234                     try {
  1236                      * Do not put the call to lookup() inside the
  1235                         /*
  1237                      * constructor.  if you do you will still be
  1236                          * Do not put the call to lookup() inside the
  1238                      * allocating space when the lookup fails.
  1237                          * constructor.  if you do you will still be
  1239                      */
  1238                          * allocating space when the lookup fails.
  1240 
  1239                          */
  1241                     addresses = nameService.lookupAllHostAddr(host);
  1240 
  1242                     success = true;
  1241                         addresses = nameService.lookupAllHostAddr(host);
  1243                     break;
       
  1244                 } catch (UnknownHostException uhe) {
       
  1245                     if (host.equalsIgnoreCase("localhost")) {
       
  1246                         InetAddress[] local = new InetAddress[] { impl.loopbackAddress() };
       
  1247                         addresses = local;
       
  1248                         success = true;
  1242                         success = true;
  1249                         break;
  1243                         break;
  1250                     }
  1244                     } catch (UnknownHostException uhe) {
  1251                     else {
  1245                         if (host.equalsIgnoreCase("localhost")) {
  1252                         addresses = unknown_array;
  1246                             InetAddress[] local = new InetAddress[] { impl.loopbackAddress() };
  1253                         success = false;
  1247                             addresses = local;
  1254                         ex = uhe;
  1248                             success = true;
       
  1249                             break;
       
  1250                         }
       
  1251                         else {
       
  1252                             addresses = unknown_array;
       
  1253                             success = false;
       
  1254                             ex = uhe;
       
  1255                         }
  1255                     }
  1256                     }
  1256                 }
  1257                 }
  1257             }
  1258 
  1258 
  1259                 // Cache the addresses.
  1259             // Cache the addresses.
  1260                 cacheAddresses(host, addresses, success);
  1260             cacheAddresses(host, addresses, success);
  1261                 if (!success && ex != null)
  1261             // Delete the host from the lookupTable, and
  1262                     throw ex;
  1262             // notify all threads waiting for the monitor
  1263             } finally {
  1263             // for lookupTable.
  1264                 // Delete host from the lookupTable and notify
  1264             updateLookupTable(host);
  1265                 // all threads waiting on the lookupTable monitor.
  1265             if (!success && ex != null)
  1266                 updateLookupTable(host);
  1266                 throw ex;
  1267             }
  1267         }
  1268         }
  1268 
  1269 
  1269         return addresses;
  1270         return addresses;
  1270     }
  1271     }
  1271 
  1272 
  1272 
  1273 
  1273     private static InetAddress[] checkLookupTable(String host) {
  1274     private static InetAddress[] checkLookupTable(String host) {
  1274         // make sure addresses is null.
       
  1275         InetAddress[] addresses = null;
       
  1276 
       
  1277         synchronized (lookupTable) {
  1275         synchronized (lookupTable) {
  1278             // If the host isn't in the lookupTable, add it in the
  1276             // If the host isn't in the lookupTable, add it in the
  1279             // lookuptable and return null. The caller should do
  1277             // lookuptable and return null. The caller should do
  1280             // the lookup.
  1278             // the lookup.
  1281             if (lookupTable.containsKey(host) == false) {
  1279             if (lookupTable.containsKey(host) == false) {
  1282                 lookupTable.put(host, null);
  1280                 lookupTable.put(host, null);
  1283                 return addresses;
  1281                 return null;
  1284             }
  1282             }
  1285 
  1283 
  1286             // If the host is in the lookupTable, it means that another
  1284             // If the host is in the lookupTable, it means that another
  1287             // thread is trying to look up the addresses of this host.
  1285             // thread is trying to look up the addresses of this host.
  1288             // This thread should wait.
  1286             // This thread should wait.
  1296 
  1294 
  1297         // The other thread has finished looking up the addresses of
  1295         // The other thread has finished looking up the addresses of
  1298         // the host. This thread should retry to get the addresses
  1296         // the host. This thread should retry to get the addresses
  1299         // from the addressCache. If it doesn't get the addresses from
  1297         // from the addressCache. If it doesn't get the addresses from
  1300         // the cache, it will try to look up the addresses itself.
  1298         // the cache, it will try to look up the addresses itself.
  1301         addresses = getCachedAddresses(host);
  1299         InetAddress[] addresses = getCachedAddresses(host);
  1302         if (addresses == null) {
  1300         if (addresses == null) {
  1303             synchronized (lookupTable) {
  1301             synchronized (lookupTable) {
  1304                 lookupTable.put(host, null);
  1302                 lookupTable.put(host, null);
       
  1303                 return null;
  1305             }
  1304             }
  1306         }
  1305         }
  1307 
  1306 
  1308         return addresses;
  1307         return addresses;
  1309     }
  1308     }