src/share/classes/java/net/InetAddress.java

Print this page




 660      * @return  a string representation of this IP address.
 661      */
 662     public String toString() {
 663         return ((hostName != null) ? hostName : "")
 664             + "/" + getHostAddress();
 665     }
 666 
 667     /*
 668      * Cached addresses - our own litle nis, not!
 669      */
 670     private static Cache addressCache = new Cache(Cache.Type.Positive);
 671 
 672     private static Cache negativeCache = new Cache(Cache.Type.Negative);
 673 
 674     private static boolean addressCacheInit = false;
 675 
 676     static InetAddress[]    unknown_array; // put THIS in cache
 677 
 678     static InetAddressImpl  impl;
 679 
 680     private static HashMap<String, InetAddress[]> lookupTable
 681         = new HashMap<String, InetAddress[]>();
 682 
 683     /**
 684      * Represents a cache entry
 685      */
 686     static final class CacheEntry {
 687 
 688         CacheEntry(InetAddress[] addresses, long expiration) {
 689             this.addresses = addresses;
 690             this.expiration = expiration;
 691         }
 692 
 693         InetAddress[] addresses;
 694         long expiration;
 695     }
 696 
 697     /**
 698      * A cache that manages entries based on a policy specified
 699      * at creation time.
 700      */
 701     static final class Cache {


 720             }
 721         }
 722 
 723         /**
 724          * Add an entry to the cache. If there's already an
 725          * entry then for this host then the entry will be
 726          * replaced.
 727          */
 728         public Cache put(String host, InetAddress[] addresses) {
 729             int policy = getPolicy();
 730             if (policy == InetAddressCachePolicy.NEVER) {
 731                 return this;
 732             }
 733 
 734             // purge any expired entries
 735 
 736             if (policy != InetAddressCachePolicy.FOREVER) {
 737 
 738                 // As we iterate in insertion order we can
 739                 // terminate when a non-expired entry is found.
 740                 LinkedList<String> expired = new LinkedList<String>();
 741                 long now = System.currentTimeMillis();
 742                 for (String key : cache.keySet()) {
 743                     CacheEntry entry = cache.get(key);
 744 
 745                     if (entry.expiration >= 0 && entry.expiration < now) {
 746                         expired.add(key);
 747                     } else {
 748                         break;
 749                     }
 750                 }
 751 
 752                 for (String key : expired) {
 753                     cache.remove(key);
 754                 }
 755             }
 756 
 757             // create new entry and add it to the cache
 758             // -- as a HashMap replaces existing entries we
 759             //    don't need to explicitly check if there is
 760             //    already an entry for this host.


1210 
1211         // Check whether the host is in the lookupTable.
1212         // 1) If the host isn't in the lookupTable when
1213         //    checkLookupTable() is called, checkLookupTable()
1214         //    would add the host in the lookupTable and
1215         //    return null. So we will do the lookup.
1216         // 2) If the host is in the lookupTable when
1217         //    checkLookupTable() is called, the current thread
1218         //    would be blocked until the host is removed
1219         //    from the lookupTable. Then this thread
1220         //    should try to look up the addressCache.
1221         //     i) if it found the addresses in the
1222         //        addressCache, checkLookupTable()  would
1223         //        return the addresses.
1224         //     ii) if it didn't find the addresses in the
1225         //         addressCache for any reason,
1226         //         it should add the host in the
1227         //         lookupTable and return null so the
1228         //         following code would do  a lookup itself.
1229         if ((addresses = checkLookupTable(host)) == null) {

1230             // This is the first thread which looks up the addresses
1231             // this host or the cache entry for this host has been
1232             // expired so this thread should do the lookup.
1233             for (NameService nameService : nameServices) {
1234                 try {
1235                     /*
1236                      * Do not put the call to lookup() inside the
1237                      * constructor.  if you do you will still be
1238                      * allocating space when the lookup fails.
1239                      */
1240 
1241                     addresses = nameService.lookupAllHostAddr(host);
1242                     success = true;
1243                     break;
1244                 } catch (UnknownHostException uhe) {
1245                     if (host.equalsIgnoreCase("localhost")) {
1246                         InetAddress[] local = new InetAddress[] { impl.loopbackAddress() };
1247                         addresses = local;
1248                         success = true;
1249                         break;
1250                     }
1251                     else {
1252                         addresses = unknown_array;
1253                         success = false;
1254                         ex = uhe;
1255                     }
1256                 }
1257             }
1258 
1259             // Cache the addresses.
1260             cacheAddresses(host, addresses, success);
1261             // Delete the host from the lookupTable, and
1262             // notify all threads waiting for the monitor
1263             // for lookupTable.
1264             updateLookupTable(host);
1265             if (!success && ex != null)
1266                 throw ex;




1267         }

1268 
1269         return addresses;
1270     }
1271 
1272 
1273     private static InetAddress[] checkLookupTable(String host) {
1274         // make sure addresses is null.
1275         InetAddress[] addresses = null;
1276 
1277         synchronized (lookupTable) {
1278             // If the host isn't in the lookupTable, add it in the
1279             // lookuptable and return null. The caller should do
1280             // the lookup.
1281             if (lookupTable.containsKey(host) == false) {
1282                 lookupTable.put(host, null);
1283                 return addresses;
1284             }
1285 
1286             // If the host is in the lookupTable, it means that another
1287             // thread is trying to look up the addresses of this host.
1288             // This thread should wait.
1289             while (lookupTable.containsKey(host)) {
1290                 try {
1291                     lookupTable.wait();
1292                 } catch (InterruptedException e) {
1293                 }
1294             }
1295         }
1296 
1297         // The other thread has finished looking up the addresses of
1298         // the host. This thread should retry to get the addresses
1299         // from the addressCache. If it doesn't get the addresses from
1300         // the cache, it will try to look up the addresses itself.
1301         addresses = getCachedAddresses(host);
1302         if (addresses == null) {
1303             synchronized (lookupTable) {
1304                 lookupTable.put(host, null);

1305             }
1306         }
1307 
1308         return addresses;
1309     }
1310 
1311     private static void updateLookupTable(String host) {
1312         synchronized (lookupTable) {
1313             lookupTable.remove(host);
1314             lookupTable.notifyAll();
1315         }
1316     }
1317 
1318     /**
1319      * Returns an <code>InetAddress</code> object given the raw IP address .
1320      * The argument is in network byte order: the highest order
1321      * byte of the address is in <code>getAddress()[0]</code>.
1322      *
1323      * <p> This method doesn't block, i.e. no reverse name service lookup
1324      * is performed.




 660      * @return  a string representation of this IP address.
 661      */
 662     public String toString() {
 663         return ((hostName != null) ? hostName : "")
 664             + "/" + getHostAddress();
 665     }
 666 
 667     /*
 668      * Cached addresses - our own litle nis, not!
 669      */
 670     private static Cache addressCache = new Cache(Cache.Type.Positive);
 671 
 672     private static Cache negativeCache = new Cache(Cache.Type.Negative);
 673 
 674     private static boolean addressCacheInit = false;
 675 
 676     static InetAddress[]    unknown_array; // put THIS in cache
 677 
 678     static InetAddressImpl  impl;
 679 
 680     private static final HashMap<String, Void> lookupTable = new HashMap<>();

 681 
 682     /**
 683      * Represents a cache entry
 684      */
 685     static final class CacheEntry {
 686 
 687         CacheEntry(InetAddress[] addresses, long expiration) {
 688             this.addresses = addresses;
 689             this.expiration = expiration;
 690         }
 691 
 692         InetAddress[] addresses;
 693         long expiration;
 694     }
 695 
 696     /**
 697      * A cache that manages entries based on a policy specified
 698      * at creation time.
 699      */
 700     static final class Cache {


 719             }
 720         }
 721 
 722         /**
 723          * Add an entry to the cache. If there's already an
 724          * entry then for this host then the entry will be
 725          * replaced.
 726          */
 727         public Cache put(String host, InetAddress[] addresses) {
 728             int policy = getPolicy();
 729             if (policy == InetAddressCachePolicy.NEVER) {
 730                 return this;
 731             }
 732 
 733             // purge any expired entries
 734 
 735             if (policy != InetAddressCachePolicy.FOREVER) {
 736 
 737                 // As we iterate in insertion order we can
 738                 // terminate when a non-expired entry is found.
 739                 LinkedList<String> expired = new LinkedList<>();
 740                 long now = System.currentTimeMillis();
 741                 for (String key : cache.keySet()) {
 742                     CacheEntry entry = cache.get(key);
 743 
 744                     if (entry.expiration >= 0 && entry.expiration < now) {
 745                         expired.add(key);
 746                     } else {
 747                         break;
 748                     }
 749                 }
 750 
 751                 for (String key : expired) {
 752                     cache.remove(key);
 753                 }
 754             }
 755 
 756             // create new entry and add it to the cache
 757             // -- as a HashMap replaces existing entries we
 758             //    don't need to explicitly check if there is
 759             //    already an entry for this host.


1209 
1210         // Check whether the host is in the lookupTable.
1211         // 1) If the host isn't in the lookupTable when
1212         //    checkLookupTable() is called, checkLookupTable()
1213         //    would add the host in the lookupTable and
1214         //    return null. So we will do the lookup.
1215         // 2) If the host is in the lookupTable when
1216         //    checkLookupTable() is called, the current thread
1217         //    would be blocked until the host is removed
1218         //    from the lookupTable. Then this thread
1219         //    should try to look up the addressCache.
1220         //     i) if it found the addresses in the
1221         //        addressCache, checkLookupTable()  would
1222         //        return the addresses.
1223         //     ii) if it didn't find the addresses in the
1224         //         addressCache for any reason,
1225         //         it should add the host in the
1226         //         lookupTable and return null so the
1227         //         following code would do  a lookup itself.
1228         if ((addresses = checkLookupTable(host)) == null) {
1229             try {
1230                 // This is the first thread which looks up the addresses
1231                 // this host or the cache entry for this host has been
1232                 // expired so this thread should do the lookup.
1233                 for (NameService nameService : nameServices) {
1234                     try {
1235                         /*
1236                          * Do not put the call to lookup() inside the
1237                          * constructor.  if you do you will still be
1238                          * allocating space when the lookup fails.
1239                          */
1240 
1241                         addresses = nameService.lookupAllHostAddr(host);
1242                         success = true;
1243                         break;
1244                     } catch (UnknownHostException uhe) {
1245                         if (host.equalsIgnoreCase("localhost")) {
1246                             InetAddress[] local = new InetAddress[] { impl.loopbackAddress() };
1247                             addresses = local;
1248                             success = true;
1249                             break;
1250                         }
1251                         else {
1252                             addresses = unknown_array;
1253                             success = false;
1254                             ex = uhe;
1255                         }
1256                     }
1257                 }
1258 
1259                 // Cache the addresses.
1260                 cacheAddresses(host, addresses, success);




1261                 if (!success && ex != null)
1262                     throw ex;
1263             } finally {
1264                 // Delete host from the lookupTable and notify
1265                 // all threads waiting on the lookupTable monitor.
1266                 updateLookupTable(host);
1267             }
1268         }
1269 
1270         return addresses;
1271     }
1272 
1273 
1274     private static InetAddress[] checkLookupTable(String host) {



1275         synchronized (lookupTable) {
1276             // If the host isn't in the lookupTable, add it in the
1277             // lookuptable and return null. The caller should do
1278             // the lookup.
1279             if (lookupTable.containsKey(host) == false) {
1280                 lookupTable.put(host, null);
1281                 return null;
1282             }
1283 
1284             // If the host is in the lookupTable, it means that another
1285             // thread is trying to look up the addresses of this host.
1286             // This thread should wait.
1287             while (lookupTable.containsKey(host)) {
1288                 try {
1289                     lookupTable.wait();
1290                 } catch (InterruptedException e) {
1291                 }
1292             }
1293         }
1294 
1295         // The other thread has finished looking up the addresses of
1296         // the host. This thread should retry to get the addresses
1297         // from the addressCache. If it doesn't get the addresses from
1298         // the cache, it will try to look up the addresses itself.
1299         InetAddress[] addresses = getCachedAddresses(host);
1300         if (addresses == null) {
1301             synchronized (lookupTable) {
1302                 lookupTable.put(host, null);
1303                 return null;
1304             }
1305         }
1306 
1307         return addresses;
1308     }
1309 
1310     private static void updateLookupTable(String host) {
1311         synchronized (lookupTable) {
1312             lookupTable.remove(host);
1313             lookupTable.notifyAll();
1314         }
1315     }
1316 
1317     /**
1318      * Returns an <code>InetAddress</code> object given the raw IP address .
1319      * The argument is in network byte order: the highest order
1320      * byte of the address is in <code>getAddress()[0]</code>.
1321      *
1322      * <p> This method doesn't block, i.e. no reverse name service lookup
1323      * is performed.