home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / net / InetAddress.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  20.9 KB  |  676 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)InetAddress.java    1.62 98/09/28
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.net;
  16.  
  17. import java.util.HashMap;
  18. import java.util.Random;
  19. import java.security.AccessController;
  20. import sun.security.action.*;
  21. import sun.net.InetAddressCachePolicy;
  22.  
  23. /**
  24.  * This class represents an Internet Protocol (IP) address.
  25.  * <p>
  26.  * Applications should use the methods <code>getLocalHost</code>,
  27.  * <code>getByName</code>, or <code>getAllByName</code> to
  28.  * create a new <code>InetAddress</code> instance.
  29.  *
  30.  * @author  Chris Warth
  31.  * @version 1.62, 09/28/98
  32.  * @see     java.net.InetAddress#getAllByName(java.lang.String)
  33.  * @see     java.net.InetAddress#getByName(java.lang.String)
  34.  * @see     java.net.InetAddress#getLocalHost()
  35.  * @since   JDK1.0
  36.  */
  37. public final
  38. class InetAddress implements java.io.Serializable {
  39.  
  40.     /**
  41.      * @serial
  42.      */
  43.     String hostName;
  44.  
  45.     /*
  46.      * Currently we only deal effectively with 32-bit addresses.
  47.      * However this field can be expanded to be a byte array
  48.      * or a 64-bit quantity without too much effort.
  49.      *
  50.      * @serial
  51.      */
  52.     int address;
  53.  
  54.     /**
  55.      * @serial
  56.      */
  57.     int family;
  58.  
  59.     /** use serialVersionUID from JDK 1.0.2 for interoperability */
  60.     private static final long serialVersionUID = 3286316764910316507L;
  61.  
  62.     /*
  63.      * Load net library into runtime, and perform initializations.
  64.      */
  65.     static {
  66.     AccessController.doPrivileged(new LoadLibraryAction("net"));
  67.         init();
  68.     }
  69.  
  70.     /**
  71.      * Constructor for the Socket.accept() method.
  72.      * This creates an empty InetAddress, which is filled in by
  73.      * the accept() method.  This InetAddress, however, is not
  74.      * put in the address cache, since it is not created by name.
  75.      */
  76.     InetAddress() {
  77.       family = impl.getInetFamily();
  78.     }
  79.  
  80.     /**
  81.      * Creates an InetAddress with the specified host name and IP address.
  82.      * @param hostName the specified host name
  83.      * @param addr the specified IP address.  The address is expected in
  84.      *          network byte order.
  85.      * @exception UnknownHostException If the address is unknown.
  86.      */
  87.     InetAddress(String hostName, byte addr[]) {
  88.     this.hostName = hostName;
  89.     this.family = impl.getInetFamily();
  90.     /*
  91.      * We must be careful here to maintain the network byte
  92.      * order of the address.  As it comes in, the most
  93.      * significant byte of the address is in addr[0].  It
  94.      * actually doesn't matter what order they end up in the
  95.      * array, as long as it is documented and consistent.
  96.      */
  97.     address  = addr[3] & 0xFF;
  98.     address |= ((addr[2] << 8) & 0xFF00);
  99.     address |= ((addr[1] << 16) & 0xFF0000);
  100.     address |= ((addr[0] << 24) & 0xFF000000);
  101.     }
  102.  
  103.     /**
  104.      * Utility routine to check if the InetAddress is a
  105.      * IP multicast address. IP multicast address is a Class D
  106.      * address i.e first four bits of the address are 1110.
  107.      * @since   JDK1.1
  108.      */
  109.     public boolean isMulticastAddress() {
  110.     return ((address & 0xf0000000) == 0xe0000000);
  111.     }
  112.  
  113.     /**
  114.      * Returns the hostname for this address.
  115.      * If the host is equal to null, then this address refers to any
  116.      * of the local machine's available network addresses.
  117.      *
  118.      * <p>If there is a security manager, its
  119.      * <code>checkConnect</code> method is first called
  120.      * with the hostname and <code>-1</code> 
  121.      * as its arguments to see if the operation is allowed.
  122.      *
  123.      * @return  the host name for this IP address.
  124.      * 
  125.      * @exception  SecurityException  if a security manager exists and its  
  126.      *  <code>checkConnect</code> method doesn't allow the operation .
  127.      * 
  128.      * @see SecurityManager#checkConnect
  129.      */
  130.     public String getHostName() {
  131.     return getHostName(true);
  132.     }
  133.  
  134.     /**
  135.      * Returns the hostname for this address.
  136.      * If the host is equal to null, then this address refers to any
  137.      * of the local machine's available network addresses.
  138.      * this is package private so SocketPermission can make calls into
  139.      * here without a security check.
  140.      *
  141.      * <p>If there is a security manager, this method first
  142.      * calls its <code>checkConnect</code> method
  143.      * with the hostname and <code>-1</code> 
  144.      * as its arguments to see if the calling code is allowed to know
  145.      * the hostname for this IP address, i.e., to connect to the host.
  146.      * 
  147.      * @return  the host name for this IP address.
  148.      * 
  149.      * @param check make security check if true
  150.      * 
  151.      * @exception  SecurityException  if a security manager exists and its  
  152.      *  <code>checkConnect</code> method doesn't allow the connection.
  153.      * 
  154.      * @see SecurityManager#checkConnect
  155.      */
  156.     String getHostName(boolean check) {
  157.     if (hostName == null) {
  158.         try {
  159.         // first lookup the hostname
  160.         hostName = impl.getHostByAddr(address);
  161.  
  162.         /* check to see if calling code is allowed to know
  163.          * the hostname for this IP address, ie, connect to the host
  164.          */
  165.         if (check) {
  166.             SecurityManager sec = System.getSecurityManager();
  167.             if (sec != null) {
  168.             sec.checkConnect(hostName, -1);
  169.             }
  170.         }
  171.  
  172.         /* now get all the IP addresses for this hostname,
  173.          * and make sure one of them matches the original IP
  174.          * address. We do this to try and prevent spoofing.
  175.          */
  176.  
  177.         InetAddress[] arr = getAllByName0(hostName, check);
  178.         boolean ok = false;
  179.  
  180.         if(arr != null) {
  181.             for(int i = 0; !ok && i < arr.length; i++) {
  182.             //System.out.println("check "+this+" "+arr[i]);
  183.             ok = (address == arr[i].address);
  184.             }
  185.         }
  186.  
  187.         //XXX: if it looks a spoof just return the address?
  188.         if (!ok) {
  189.             hostName = getHostAddress();
  190.             return getHostAddress();
  191.         }
  192.  
  193.         } catch (SecurityException e) {
  194.         hostName = getHostAddress();
  195.         } catch (UnknownHostException e) {
  196.         hostName = getHostAddress();
  197.         }
  198.     }
  199.     return hostName;
  200.     }
  201.  
  202.     /**
  203.      * Returns the raw IP address of this <code>InetAddress</code>
  204.      * object. The result is in network byte order: the highest order
  205.      * byte of the address is in <code>getAddress()[0]</code>.
  206.      *
  207.      * @return  the raw IP address of this object.
  208.      */
  209.     public byte[] getAddress() {
  210.     byte[] addr = new byte[4];
  211.  
  212.     addr[0] = (byte) ((address >>> 24) & 0xFF);
  213.     addr[1] = (byte) ((address >>> 16) & 0xFF);
  214.     addr[2] = (byte) ((address >>> 8) & 0xFF);
  215.     addr[3] = (byte) (address & 0xFF);
  216.     return addr;
  217.     }
  218.  
  219.     /**
  220.      * Returns the IP address string "%d.%d.%d.%d".
  221.      *
  222.      * @return  the raw IP address in a string format.
  223.      * @since   JDK1.0.2
  224.      */
  225.     public String getHostAddress() {
  226.          return ((address >>> 24) & 0xFF) + "." +
  227.                 ((address >>> 16) & 0xFF) + "." +
  228.                 ((address >>>  8) & 0xFF) + "." +
  229.                 ((address >>>  0) & 0xFF);
  230.      }
  231.  
  232.  
  233.     /**
  234.      * Returns a hashcode for this IP address.
  235.      *
  236.      * @return  a hash code value for this IP address.
  237.      */
  238.     public int hashCode() {
  239.     return address;
  240.     }
  241.  
  242.     /**
  243.      * Compares this object against the specified object.
  244.      * The result is <code>true</code> if and only if the argument is
  245.      * not <code>null</code> and it represents the same IP address as
  246.      * this object.
  247.      * <p>
  248.      * Two instances of <code>InetAddress</code> represent the same IP
  249.      * address if the length of the byte arrays returned by
  250.      * <code>getAddress</code> is the same for both, and each of the
  251.      * array components is the same for the byte arrays.
  252.      *
  253.      * @param   obj   the object to compare against.
  254.      * @return  <code>true</code> if the objects are the same;
  255.      *          <code>false</code> otherwise.
  256.      * @see     java.net.InetAddress#getAddress()
  257.      */
  258.     public boolean equals(Object obj) {
  259.     return (obj != null) && (obj instanceof InetAddress) &&
  260.         (((InetAddress)obj).address == address);
  261.     }
  262.  
  263.     /**
  264.      * Converts this IP address to a <code>String</code>.
  265.      *
  266.      * @return  a string representation of this IP address.
  267.      */
  268.     public String toString() {
  269.     return getHostName() + "/" + getHostAddress();
  270.     }
  271.  
  272.     /*
  273.      * Cached addresses - our own litle nis, not!
  274.      */
  275.     private static HashMap        addressCache = new HashMap();
  276.     private static InetAddress        unknownAddress;
  277.     private static InetAddress      localHost;
  278.     private static InetAddress[]    unknown_array; // put THIS in cache
  279.     static InetAddress        anyLocalAddress;
  280.     static InetAddressImpl  impl;
  281.  
  282.     static final class CacheEntry {
  283.  
  284.     CacheEntry(String hostname, Object address, long expiration) {
  285.         this.hostname = hostname;
  286.         this.address = address;
  287.         this.expiration = expiration;
  288.     }
  289.  
  290.     String hostname;
  291.     Object address;
  292.     long expiration;
  293.     }
  294.  
  295.     private static void cacheAddress(String hostname, Object address) {
  296.     synchronized (InetAddressCachePolicy.class) {
  297.     // if the cache policy is to cache nothing, just return
  298.         if (InetAddressCachePolicy.get() == 0) {
  299.         return;
  300.         }
  301.         long expiration = -1;
  302.         if (InetAddressCachePolicy.get() != InetAddressCachePolicy.FOREVER) {
  303.         expiration = System.currentTimeMillis() + 
  304.             (InetAddressCachePolicy.get() * 1000);
  305.         }
  306.         cacheAddress(hostname, address, expiration);
  307.     }
  308.     }
  309.  
  310.     private static void cacheAddress(String hostname, Object address, long expiration) {
  311.         hostname = hostname.toLowerCase();
  312.     synchronized (addressCache) {
  313.         CacheEntry entry = (CacheEntry)addressCache.get(hostname);
  314.         if (entry == null) {
  315.         entry = new CacheEntry(hostname, address, expiration);
  316.         addressCache.put(hostname, entry);
  317.         } else {
  318.         entry.address = address;
  319.         entry.expiration = expiration;
  320.         }
  321.     }
  322.     }
  323.  
  324.     private static Object getCachedAddress(String hostname) {
  325.         hostname = hostname.toLowerCase();
  326.     synchronized (addressCache) {
  327.         if (InetAddressCachePolicy.get() == 0) {
  328.         return null;
  329.         }
  330.         CacheEntry entry = (CacheEntry)addressCache.get(hostname);
  331.         if (entry != null && entry.expiration < System.currentTimeMillis() &&
  332.         entry.expiration >= 0) {
  333.         entry = null;
  334.         }
  335.         return entry != null ? entry.address : null;
  336.     }
  337.     }
  338.  
  339.     /*
  340.      * generic localHost to give back to applets
  341.      * - private so not API delta
  342.      */
  343.     private static InetAddress      loopbackHost;
  344.  
  345.     static {
  346.     /*
  347.      * Property "impl.prefix" will be prepended to the classname
  348.      * of the implementation object we instantiate, to which we
  349.      * delegate the real work (like native methods).  This
  350.      * property can vary across implementations of the java.
  351.      * classes.  The default is an empty String "".
  352.      */
  353.     String prefix = (String)AccessController.doPrivileged(
  354.               new GetPropertyAction("impl.prefix", ""));
  355.  
  356.     try {
  357.         impl = null;
  358.         impl = (InetAddressImpl)(Class.forName("java.net." + prefix +
  359.                            "InetAddressImpl")
  360.                      .newInstance());
  361.     } catch (ClassNotFoundException e) {
  362.         System.err.println("Class not found: java.net." + prefix +
  363.                    "InetAddressImpl:\ncheck impl.prefix property " +
  364.                    "in your properties file.");
  365.     } catch (InstantiationException e) {
  366.         System.err.println("Could not instantiate: java.net." + prefix +
  367.                    "InetAddressImpl:\ncheck impl.prefix property " +
  368.                    "in your properties file.");
  369.     } catch (IllegalAccessException e) {
  370.         System.err.println("Cannot access class: java.net." + prefix +
  371.                    "InetAddressImpl:\ncheck impl.prefix property " +
  372.                    "in your properties file.");
  373.     }
  374.  
  375.     if (impl == null) {
  376.         try {
  377.         impl = (InetAddressImpl)(Class.forName("java.net.InetAddressImpl")
  378.                      .newInstance());
  379.         } catch (Exception e) {
  380.         throw new Error("System property impl.prefix incorrect");
  381.         }
  382.     }
  383.  
  384.     unknownAddress = new InetAddress();
  385.     anyLocalAddress = new InetAddress();
  386.     impl.makeAnyLocalAddress(anyLocalAddress);
  387.     byte[] IP = new byte[4];
  388.     IP[0] = 0x7F;
  389.     IP[1] = 0x00;
  390.     IP[2] = 0x00;
  391.     IP[3] = 0x01;
  392.     loopbackHost = new InetAddress("localhost", IP);
  393.  
  394.     /* find the local host name */
  395.     try {
  396.         localHost = new InetAddress();
  397.         localHost.hostName = impl.getLocalHostName();
  398.         /* we explicitly leave the address of the local host
  399.          * uninitialized.  A DNS lookup in this, the static
  400.          * initializer, will cause a machine disconnected
  401.          * from the network to hang - it'll be trying to query
  402.          * a DNS server that isn't there.
  403.          *
  404.          * Instead, we just get the hostname of the local host.
  405.          * The native code for this just calls gethostname()
  406.          * which should be pretty innocuous - it shouldn't try
  407.          * to contact a DNS server.  If any application
  408.          * calls InetAddress.getLocalHost(), we initialize
  409.          * the local host's address there if not already initialized.
  410.          *
  411.          * Note that for this to work it is also essential that
  412.          * the localHost InetAddress is _NOT_ put into the address cache
  413.          * here in the static initializer (which happens if we call
  414.          * getByName() from the static initializer).  It _IS_ OK
  415.          * to put it in the addressCache after initialization.
  416.          *
  417.          * The unitialized state of the localHost's address is -1,
  418.          * or IP address 255.255.255.255 which we know cannot be
  419.          * a legal host address.
  420.          */
  421.         localHost.address = -1;
  422.     } catch (Exception ex) { /* this shouldn't happen */
  423.         localHost = unknownAddress;
  424.     }
  425.  
  426.     /* cache the name/address pair "0.0.0.0"/0.0.0.0 */
  427.     String unknownByAddr = "0.0.0.0";
  428.     unknown_array = new InetAddress[1];
  429.     unknown_array[0] = new InetAddress(unknownByAddr,
  430.                        unknownAddress.getAddress());
  431.     cacheAddress(unknownByAddr, unknown_array, InetAddressCachePolicy.FOREVER);
  432.     }
  433.  
  434.     /**
  435.      * Determines the IP address of a host, given the host's name. The
  436.      * host name can either be a machine name, such as
  437.      * "<code>java.sun.com</code>", or a string representing its IP
  438.      * address, such as "<code>206.26.48.100</code>".
  439.      *
  440.      * @param      host   the specified host, or <code>null</code> for the
  441.      *                    local host.
  442.      * @return     an IP address for the given host name.
  443.      * @exception  UnknownHostException  if no IP address for the
  444.      *               <code>host</code> could be found.
  445.      */
  446.     public static InetAddress getByName(String host)
  447.     throws UnknownHostException {
  448.     Object obj = null;
  449.     if (host == null || host.length() == 0) {
  450.         return loopbackHost;
  451.     }
  452.         if (!Character.isDigit(host.charAt(0))) {
  453.         return getAllByName0(host)[0];
  454.     } else {
  455.         /* The string (probably) represents a numerical IP address.
  456.          * Parse it into an int, don't do uneeded reverese lookup,
  457.          * leave hostName null, don't cache.  If it isn't an IP address,
  458.          * (i.e., not "%d.%d.%d.%d") or if any element > 0xFF,
  459.          * we treat it as a hostname, and lookup that way.
  460.          * This seems to be 100% compliant to the RFC1123 spec:
  461.          * a partial hostname like 3com.domain4 is technically valid.
  462.          */
  463.  
  464.         int IP = 0x00;
  465.         int hitDots = 0;
  466.         char[] data = host.toCharArray();
  467.  
  468.         for(int i = 0; i < data.length; i++) {
  469.         char c = data[i];
  470.         if (c < 48 || c > 57) { // !digit
  471.             return getAllByName0(host)[0];
  472.         }
  473.         int b = 0x00;
  474.         while(c != '.') {
  475.             if (c < 48 || c > 57) { // !digit
  476.             return getAllByName0(host)[0];
  477.             }
  478.             b = b*10 + c - '0';
  479.  
  480.             if (++i >= data.length)
  481.             break;
  482.             c = data[i];
  483.         }
  484.         if(b > 0xFF) { /* bogus - bigger than a byte */
  485.             return getAllByName0(host)[0];
  486.         }
  487.         IP = (IP << 8) + b;
  488.         hitDots++;
  489.         }
  490.  
  491.         if(hitDots != 4 || host.endsWith(".")) {
  492.         return getAllByName0(host)[0];
  493.         }
  494.  
  495.         InetAddress in = new InetAddress();
  496.         in.address = IP;
  497.         in.hostName = null;
  498.         return in;
  499.     }
  500.  
  501.     }
  502.  
  503.     /**
  504.      * Determines all the IP addresses of a host, given the host's name.
  505.      * The host name can either be a machine name, such as
  506.      * "<code>java.sun.com</code>", or a string representing
  507.      * its IP address, such as "<code>206.26.48.100</code>".
  508.      *
  509.      * <p>If there is a security manager and <code>host</code> is not 
  510.      * null and <code>host.length() </code> is not equal to zero, the
  511.      * security manager's
  512.      * <code>checkConnect</code> method is called
  513.      * with the hostname and <code>-1</code> 
  514.      * as its arguments to see if the operation is allowed.
  515.      *
  516.      * @param      host   the name of the host.
  517.      * @return     an array of all the IP addresses for a given host name.
  518.      * 
  519.      * @exception  UnknownHostException  if no IP address for the
  520.      *               <code>host</code> could be found.
  521.      * @exception  SecurityException  if a security manager exists and its  
  522.      *               <code>checkConnect</code> method doesn't allow the operation.
  523.      * 
  524.      * @see SecurityManager#checkConnect
  525.      */
  526.     public static InetAddress[] getAllByName(String host)
  527.     throws UnknownHostException {
  528.  
  529.     if (host == null || host.length() == 0) {
  530.         throw new UnknownHostException("empty string");
  531.     }
  532.     if(Character.isDigit(host.charAt(0))) {
  533.         InetAddress[] ret = new InetAddress[1];
  534.         ret[0] = getByName(host);
  535.         return ret;
  536.     } else {
  537.         return getAllByName0(host);
  538.     }
  539.     }
  540.  
  541.     private static InetAddress[] getAllByName0 (String host)
  542.     throws UnknownHostException
  543.     {
  544.     return getAllByName0(host, true);
  545.     }
  546.  
  547.     /**
  548.      * package private so SocketPermission can call it
  549.      */
  550.     static InetAddress[] getAllByName0 (String host, boolean check)
  551.     throws UnknownHostException  {
  552.     /* If it gets here it is presumed to be a hostname */
  553.     /* Cache.get can return: null, unknownAddress, or InetAddress[] */
  554.         Object obj = null;
  555.     Object objcopy = null;
  556.  
  557.     /* make sure the connection to the host is allowed, before we
  558.      * give out a hostname
  559.      */
  560.     if (check) {
  561.         SecurityManager security = System.getSecurityManager();
  562.         if (security != null) {
  563.         security.checkConnect(host, -1);
  564.         }
  565.     }
  566.  
  567.     synchronized (addressCache) {
  568.         obj = getCachedAddress(host);
  569.  
  570.     /* If no entry in cache, then do the host lookup */
  571.  
  572.         if (obj == null) {
  573.         try {
  574.             /*
  575.              * Do not put the call to lookup() inside the
  576.              * constructor.  if you do you will still be
  577.              * allocating space when the lookup fails.
  578.              */
  579.             byte[][] byte_array = impl.lookupAllHostAddr(host);
  580.             InetAddress[] addr_array =
  581.             new InetAddress[byte_array.length];
  582.  
  583.             for (int i = 0; i < byte_array.length; i++) {
  584.             byte addr[] = byte_array[i];
  585.             addr_array[i] = new InetAddress(host, addr);
  586.             }
  587.             obj = addr_array;
  588.         } catch (UnknownHostException e) {
  589.             obj  = unknown_array;
  590.         }
  591.         cacheAddress(host, obj);
  592.         }
  593.     } /* end synchronized block */
  594.  
  595.     if (obj == unknown_array) {
  596.         /*
  597.          * We currently cache the fact that a host is unknown.
  598.          */
  599.         throw new UnknownHostException(host);
  600.     }
  601.  
  602.     /* Make a copy of the InetAddress array */
  603.     try {
  604.           objcopy = ((InetAddress [])obj).clone();
  605.           // the following line is a hack, to ensure that the code
  606.           // can compile for both the broken compiler and the fixed one.
  607.           if (objcopy == null)
  608.           throw new CloneNotSupportedException();
  609.     } catch (CloneNotSupportedException cnse) {
  610.           cnse.printStackTrace();
  611.     }
  612.  
  613.     return (InetAddress [])objcopy;
  614.     }
  615.  
  616.     /**
  617.      * Returns the local host.
  618.      *
  619.      * <p>If there is a security manager, its
  620.      * <code>checkConnect</code> method is called
  621.      * with the local host name and <code>-1</code> 
  622.      * as its arguments to see if the operation is allowed.
  623.      *
  624.      * @return     the IP address of the local host.
  625.      * 
  626.      * @exception  UnknownHostException  if no IP address for the
  627.      *               <code>host</code> could be found.
  628.      * @exception  SecurityException  if a security manager exists and its  
  629.      *               <code>checkConnect</code> method doesn't allow the operation.
  630.      * 
  631.      * @see SecurityManager#checkConnect
  632.      */
  633.     public synchronized static InetAddress getLocalHost() throws UnknownHostException {
  634.         if (localHost.equals(unknownAddress)) {
  635.         throw new UnknownHostException();
  636.     }
  637.  
  638.         /* make sure the connection to the host is allowed: if yes,
  639.      * return the "real" localHost; if not, return loopback "127.0.0.1"
  640.      */
  641.     SecurityManager security = System.getSecurityManager();
  642.     try {
  643.  
  644.         /* If the localhost's address is not initialized yet, initialize
  645.          * it.  It is no longer initialized in the static initializer
  646.          * (see comment there).
  647.          */
  648.  
  649.         if (localHost.address == -1) {
  650.         localHost = getAllByName(localHost.hostName)[0];
  651.         /* This puts it in the address cache as well */
  652.         }
  653.  
  654.         if (security != null)
  655.         security.checkConnect(localHost.getHostName(), -1);
  656.     } catch (java.lang.SecurityException e) {
  657.         return loopbackHost;
  658.     }
  659.     return localHost;
  660.     }
  661.  
  662.     /**
  663.      * Perform class load-time initializations.
  664.      */
  665.     private static native void init();
  666. }
  667.  
  668. class InetAddressImpl {
  669.     native String getLocalHostName() throws UnknownHostException;
  670.     native void makeAnyLocalAddress(InetAddress addr);
  671.     native byte[][]
  672.         lookupAllHostAddr(String hostname) throws UnknownHostException;
  673.     native String getHostByAddr(int addr) throws UnknownHostException;
  674.     native int getInetFamily();
  675. }
  676.