changeset 7016:95eeca6dc691

8015743: Address internet addresses Summary: moved Inet6Address fields to holder class Reviewed-by: chegar, alanb, skoivu, khazra
author michaelm
date Wed, 03 Jul 2013 17:54:38 +0100
parents 4a9ced03945a
children 4fc1467017ea
files src/share/classes/java/net/Inet6Address.java src/share/classes/java/net/InetAddress.java src/share/native/java/net/Inet6Address.c src/share/native/java/net/net_util.c src/share/native/java/net/net_util.h src/solaris/native/java/net/Inet6AddressImpl.c src/solaris/native/java/net/NetworkInterface.c src/solaris/native/java/net/PlainDatagramSocketImpl.c src/solaris/native/java/net/net_util_md.c src/windows/native/java/net/Inet6AddressImpl.c src/windows/native/java/net/NetworkInterface.c src/windows/native/java/net/NetworkInterface_winXP.c src/windows/native/java/net/TwoStacksPlainSocketImpl.c test/java/net/Inet6Address/serialize/Serialize.java
diffstat 14 files changed, 662 insertions(+), 245 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/net/Inet6Address.java	Tue Jul 02 15:17:25 2013 -0700
+++ b/src/share/classes/java/net/Inet6Address.java	Wed Jul 03 17:54:38 2013 +0100
@@ -26,6 +26,8 @@
 package java.net;
 
 import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
 import java.io.IOException;
 import java.io.InvalidObjectException;
 import java.util.Enumeration;
@@ -171,36 +173,196 @@
      */
     private transient int cached_scope_id = 0;
 
-    /**
-     * Holds a 128-bit (16 bytes) IPv6 address.
-     *
-     * @serial
-     */
-    byte[] ipaddress;
+    private class Inet6AddressHolder {
+
+        private Inet6AddressHolder() {
+            ipaddress = new byte[INADDRSZ];
+        }
+
+        private Inet6AddressHolder(
+            byte[] ipaddress, int scope_id, boolean scope_id_set,
+            NetworkInterface ifname, boolean scope_ifname_set)
+        {
+            this.ipaddress = ipaddress;
+            this.scope_id = scope_id;
+            this.scope_id_set = scope_id_set;
+            this.scope_ifname_set = scope_ifname_set;
+            this.scope_ifname = ifname;
+        }
+
+        /**
+         * Holds a 128-bit (16 bytes) IPv6 address.
+         */
+        byte[] ipaddress;
+
+        /**
+         * scope_id. The scope specified when the object is created. If the object is created
+         * with an interface name, then the scope_id is not determined until the time it is needed.
+         */
+        int scope_id = 0;
+
+        /**
+         * This will be set to true when the scope_id field contains a valid
+         * integer scope_id.
+         */
+        boolean scope_id_set = false;
+
+        /**
+         * scoped interface. scope_id is derived from this as the scope_id of the first
+         * address whose scope is the same as this address for the named interface.
+         */
+        NetworkInterface scope_ifname = null;
+
+        /**
+         * set if the object is constructed with a scoped interface instead of a
+         * numeric scope id.
+         */
+        boolean scope_ifname_set = false;
 
-    /**
-     * scope_id. The scope specified when the object is created. If the object is created
-     * with an interface name, then the scope_id is not determined until the time it is needed.
-     */
-    private int scope_id = 0;
+        void setAddr(byte addr[]) {
+            if (addr.length == INADDRSZ) { // normal IPv6 address
+                System.arraycopy(addr, 0, ipaddress, 0, INADDRSZ);
+            }
+        }
+
+        void init(byte addr[], int scope_id) {
+            setAddr(addr);
+
+            if (scope_id >= 0) {
+                this.scope_id = scope_id;
+                this.scope_id_set = true;
+            }
+        }
+
+        void init(byte addr[], NetworkInterface nif)
+            throws UnknownHostException
+        {
+            setAddr(addr);
+
+            if (nif != null) {
+                this.scope_id = deriveNumericScope(ipaddress, nif);
+                this.scope_id_set = true;
+                this.scope_ifname = nif;
+                this.scope_ifname_set = true;
+            }
+        }
+
+        String getHostAddress() {
+            String s = numericToTextFormat(ipaddress);
+            if (scope_ifname_set) { /* must check this first */
+                s = s + "%" + scope_ifname.getName();
+            } else if (scope_id_set) {
+                s = s + "%" + scope_id;
+            }
+            return s;
+        }
+
+        public boolean equals(Object o) {
+            if (! (o instanceof Inet6AddressHolder)) {
+                return false;
+            }
+            Inet6AddressHolder that = (Inet6AddressHolder)o;
+
+            for (int i = 0; i < INADDRSZ; i++) {
+                if (this.ipaddress[i] != that.ipaddress[i])
+                    return false;
+            }
 
-    /**
-     * This will be set to true when the scope_id field contains a valid
-     * integer scope_id.
-     */
-    private boolean scope_id_set = false;
+            return true;
+        }
+
+        public int hashCode() {
+            if (ipaddress != null) {
+
+                int hash = 0;
+                int i=0;
+                while (i<INADDRSZ) {
+                    int j=0;
+                    int component=0;
+                    while (j<4 && i<INADDRSZ) {
+                        component = (component << 8) + ipaddress[i];
+                        j++;
+                        i++;
+                    }
+                    hash += component;
+                }
+                return hash;
+
+            } else {
+                return 0;
+            }
+        }
+
+        boolean isIPv4CompatibleAddress() {
+            if ((ipaddress[0] == 0x00) && (ipaddress[1] == 0x00) &&
+                (ipaddress[2] == 0x00) && (ipaddress[3] == 0x00) &&
+                (ipaddress[4] == 0x00) && (ipaddress[5] == 0x00) &&
+                (ipaddress[6] == 0x00) && (ipaddress[7] == 0x00) &&
+                (ipaddress[8] == 0x00) && (ipaddress[9] == 0x00) &&
+                (ipaddress[10] == 0x00) && (ipaddress[11] == 0x00))  {
+                return true;
+            }
+            return false;
+        }
+
+        boolean isMulticastAddress() {
+            return ((ipaddress[0] & 0xff) == 0xff);
+        }
 
-    /**
-     * scoped interface. scope_id is derived from this as the scope_id of the first
-     * address whose scope is the same as this address for the named interface.
-     */
-    private transient NetworkInterface scope_ifname = null;
+        boolean isAnyLocalAddress() {
+            byte test = 0x00;
+            for (int i = 0; i < INADDRSZ; i++) {
+                test |= ipaddress[i];
+            }
+            return (test == 0x00);
+        }
+
+        boolean isLoopbackAddress() {
+            byte test = 0x00;
+            for (int i = 0; i < 15; i++) {
+                test |= ipaddress[i];
+            }
+            return (test == 0x00) && (ipaddress[15] == 0x01);
+        }
+
+        boolean isLinkLocalAddress() {
+            return ((ipaddress[0] & 0xff) == 0xfe
+                    && (ipaddress[1] & 0xc0) == 0x80);
+        }
+
+
+        boolean isSiteLocalAddress() {
+            return ((ipaddress[0] & 0xff) == 0xfe
+                    && (ipaddress[1] & 0xc0) == 0xc0);
+        }
 
-    /**
-     * set if the object is constructed with a scoped interface instead of a
-     * numeric scope id.
-     */
-    private boolean scope_ifname_set = false;
+        boolean isMCGlobal() {
+            return ((ipaddress[0] & 0xff) == 0xff
+                    && (ipaddress[1] & 0x0f) == 0x0e);
+        }
+
+        boolean isMCNodeLocal() {
+            return ((ipaddress[0] & 0xff) == 0xff
+                    && (ipaddress[1] & 0x0f) == 0x01);
+        }
+
+        boolean isMCLinkLocal() {
+            return ((ipaddress[0] & 0xff) == 0xff
+                    && (ipaddress[1] & 0x0f) == 0x02);
+        }
+
+        boolean isMCSiteLocal() {
+            return ((ipaddress[0] & 0xff) == 0xff
+                    && (ipaddress[1] & 0x0f) == 0x05);
+        }
+
+        boolean isMCOrgLocal() {
+            return ((ipaddress[0] & 0xff) == 0xff
+                    && (ipaddress[1] & 0x0f) == 0x08);
+        }
+    }
+
+    private final transient Inet6AddressHolder holder6;
 
     private static final long serialVersionUID = 6880410070516793377L;
 
@@ -213,37 +375,33 @@
 
     Inet6Address() {
         super();
-        holder().hostName = null;
-        ipaddress = new byte[INADDRSZ];
-        holder().family = IPv6;
+        holder.init(null, IPv6);
+        holder6 = new Inet6AddressHolder();
     }
 
     /* checking of value for scope_id should be done by caller
      * scope_id must be >= 0, or -1 to indicate not being set
      */
     Inet6Address(String hostName, byte addr[], int scope_id) {
-        holder().hostName = hostName;
-        if (addr.length == INADDRSZ) { // normal IPv6 address
-            holder().family = IPv6;
-            ipaddress = addr.clone();
-        }
-        if (scope_id >= 0) {
-            this.scope_id = scope_id;
-            scope_id_set = true;
-        }
+        holder.init(hostName, IPv6);
+        holder6 = new Inet6AddressHolder();
+        holder6.init(addr, scope_id);
     }
 
     Inet6Address(String hostName, byte addr[]) {
+        holder6 = new Inet6AddressHolder();
         try {
             initif (hostName, addr, null);
         } catch (UnknownHostException e) {} /* cant happen if ifname is null */
     }
 
     Inet6Address (String hostName, byte addr[], NetworkInterface nif) throws UnknownHostException {
+        holder6 = new Inet6AddressHolder();
         initif (hostName, addr, nif);
     }
 
     Inet6Address (String hostName, byte addr[], String ifname) throws UnknownHostException {
+        holder6 = new Inet6AddressHolder();
         initstr (hostName, addr, ifname);
     }
 
@@ -325,17 +483,13 @@
     }
 
     private void initif(String hostName, byte addr[],NetworkInterface nif) throws UnknownHostException {
-        holder().hostName = hostName;
+        int family = -1;
+        holder6.init(addr, nif);
+
         if (addr.length == INADDRSZ) { // normal IPv6 address
-            holder().family = IPv6;
-            ipaddress = addr.clone();
+            family = IPv6;
         }
-        if (nif != null) {
-            this.scope_ifname = nif;
-            scope_ifname_set = true;
-            scope_id = deriveNumericScope (nif);
-            scope_id_set = true;
-        }
+        holder.init(hostName, family);
     }
 
     /* check the two Ipv6 addresses and return false if they are both
@@ -343,18 +497,21 @@
      * (ie. one is sitelocal and the other linklocal)
      * return true otherwise.
      */
-    private boolean differentLocalAddressTypes(Inet6Address other) {
+    private static boolean differentLocalAddressTypes(
+        byte[] thisAddr, byte[] otherAddr) {
 
-        if (isLinkLocalAddress() && !other.isLinkLocalAddress()) {
+        if (Inet6Address.isLinkLocalAddress(thisAddr) &&
+                !Inet6Address.isLinkLocalAddress(otherAddr)) {
             return false;
         }
-        if (isSiteLocalAddress() && !other.isSiteLocalAddress()) {
+        if (Inet6Address.isSiteLocalAddress(thisAddr) &&
+                !Inet6Address.isSiteLocalAddress(otherAddr)) {
             return false;
         }
         return true;
     }
 
-    private int deriveNumericScope (NetworkInterface ifc) throws UnknownHostException {
+    private static int deriveNumericScope (byte[] thisAddr, NetworkInterface ifc) throws UnknownHostException {
         Enumeration<InetAddress> addresses = ifc.getInetAddresses();
         while (addresses.hasMoreElements()) {
             InetAddress addr = addresses.nextElement();
@@ -363,12 +520,12 @@
             }
             Inet6Address ia6_addr = (Inet6Address)addr;
             /* check if site or link local prefixes match */
-            if (!differentLocalAddressTypes(ia6_addr)){
+            if (!differentLocalAddressTypes(thisAddr, ia6_addr.getAddress())){
                 /* type not the same, so carry on searching */
                 continue;
             }
             /* found a matching address - return its scope_id */
-            return ia6_addr.scope_id;
+            return ia6_addr.getScopeId();
         }
         throw new UnknownHostException ("no scope_id found");
     }
@@ -383,41 +540,61 @@
         while (en.hasMoreElements()) {
             NetworkInterface ifc = en.nextElement();
             if (ifc.getName().equals (ifname)) {
-                Enumeration addresses = ifc.getInetAddresses();
-                while (addresses.hasMoreElements()) {
-                    InetAddress addr = (InetAddress)addresses.nextElement();
-                    if (!(addr instanceof Inet6Address)) {
-                        continue;
-                    }
-                    Inet6Address ia6_addr = (Inet6Address)addr;
-                    /* check if site or link local prefixes match */
-                    if (!differentLocalAddressTypes(ia6_addr)){
-                        /* type not the same, so carry on searching */
-                        continue;
-                    }
-                    /* found a matching address - return its scope_id */
-                    return ia6_addr.scope_id;
-                }
+                return deriveNumericScope(holder6.ipaddress, ifc);
             }
         }
         throw new UnknownHostException ("No matching address found for interface : " +ifname);
     }
 
     /**
+     * @serialField ipaddress byte[]
+     * @serialField scope_id int
+     * @serialField scope_id_set boolean
+     * @serialField scope_ifname_set boolean
+     * @serialField ifname String
+     */
+
+    private static final ObjectStreamField[] serialPersistentFields = {
+         new ObjectStreamField("ipaddress", byte[].class),
+         new ObjectStreamField("scope_id", int.class),
+         new ObjectStreamField("scope_id_set", boolean.class),
+         new ObjectStreamField("scope_ifname_set", boolean.class),
+         new ObjectStreamField("ifname", String.class)
+    };
+
+    private static final long FIELDS_OFFSET;
+    private static final sun.misc.Unsafe UNSAFE;
+
+    static {
+        try {
+            sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+            FIELDS_OFFSET = unsafe.objectFieldOffset(
+                    Inet6Address.class.getDeclaredField("holder6"));
+            UNSAFE = unsafe;
+        } catch (ReflectiveOperationException e) {
+            throw new Error(e);
+        }
+    }
+
+    /**
      * restore the state of this object from stream
      * including the scope information, only if the
      * scoped interface name is valid on this system
      */
     private void readObject(ObjectInputStream s)
         throws IOException, ClassNotFoundException {
-        scope_ifname = null;
-        scope_ifname_set = false;
+        NetworkInterface scope_ifname = null;
 
         if (getClass().getClassLoader() != null) {
             throw new SecurityException ("invalid address type");
         }
 
-        s.defaultReadObject();
+        ObjectInputStream.GetField gf = s.readFields();
+        byte[] ipaddress = (byte[])gf.get("ipaddress", null);
+        int scope_id = (int)gf.get("scope_id", -1);
+        boolean scope_id_set = (boolean)gf.get("scope_id_set", false);
+        boolean scope_ifname_set = (boolean)gf.get("scope_ifname_set", false);
+        String ifname = (String)gf.get("ifname", null);
 
         if (ifname != null && !"".equals (ifname)) {
             try {
@@ -430,7 +607,7 @@
                     scope_id = 0;
                 } else {
                     try {
-                        scope_id = deriveNumericScope (scope_ifname);
+                        scope_id = deriveNumericScope (ipaddress, scope_ifname);
                     } catch (UnknownHostException e) {
                         // typically should not happen, but it may be that
                         // the machine being used for deserialization has
@@ -438,8 +615,8 @@
                     }
                 }
             } catch (SocketException e) {}
+        }
 
-        }
         /* if ifname was not supplied, then the numeric info is used */
 
         ipaddress = ipaddress.clone();
@@ -450,9 +627,37 @@
                                              ipaddress.length);
         }
 
-        if (holder().getFamily() != IPv6) {
+        if (holder.getFamily() != IPv6) {
             throw new InvalidObjectException("invalid address family type");
         }
+
+        Inet6AddressHolder h = new Inet6AddressHolder(
+            ipaddress, scope_id, scope_id_set, scope_ifname, scope_ifname_set
+        );
+
+        UNSAFE.putObject(this, FIELDS_OFFSET, h);
+    }
+
+    /**
+     * default behavior is overridden in order to write the
+     * scope_ifname field as a String, rather than a NetworkInterface
+     * which is not serializable
+     */
+    private synchronized void writeObject(ObjectOutputStream s)
+        throws IOException
+    {
+            String ifname = null;
+
+        if (holder6.scope_ifname_set) {
+            ifname = holder6.scope_ifname.getName();
+        }
+        ObjectOutputStream.PutField pfields = s.putFields();
+        pfields.put("ipaddress", holder6.ipaddress);
+        pfields.put("scope_id", holder6.scope_id);
+        pfields.put("scope_id_set", holder6.scope_id_set);
+        pfields.put("scope_ifname_set", holder6.scope_ifname_set);
+        pfields.put("ifname", ifname);
+        s.writeFields();
     }
 
     /**
@@ -466,7 +671,7 @@
      */
     @Override
     public boolean isMulticastAddress() {
-        return ((ipaddress[0] & 0xff) == 0xff);
+        return holder6.isMulticastAddress();
     }
 
     /**
@@ -477,11 +682,7 @@
      */
     @Override
     public boolean isAnyLocalAddress() {
-        byte test = 0x00;
-        for (int i = 0; i < INADDRSZ; i++) {
-            test |= ipaddress[i];
-        }
-        return (test == 0x00);
+        return holder6.isAnyLocalAddress();
     }
 
     /**
@@ -493,11 +694,7 @@
      */
     @Override
     public boolean isLoopbackAddress() {
-        byte test = 0x00;
-        for (int i = 0; i < 15; i++) {
-            test |= ipaddress[i];
-        }
-        return (test == 0x00) && (ipaddress[15] == 0x01);
+        return holder6.isLoopbackAddress();
     }
 
     /**
@@ -509,6 +706,11 @@
      */
     @Override
     public boolean isLinkLocalAddress() {
+        return holder6.isLinkLocalAddress();
+    }
+
+    /* static version of above */
+    static boolean isLinkLocalAddress(byte[] ipaddress) {
         return ((ipaddress[0] & 0xff) == 0xfe
                 && (ipaddress[1] & 0xc0) == 0x80);
     }
@@ -522,6 +724,11 @@
      */
     @Override
     public boolean isSiteLocalAddress() {
+        return holder6.isSiteLocalAddress();
+    }
+
+    /* static version of above */
+    static boolean isSiteLocalAddress(byte[] ipaddress) {
         return ((ipaddress[0] & 0xff) == 0xfe
                 && (ipaddress[1] & 0xc0) == 0xc0);
     }
@@ -536,8 +743,7 @@
      */
     @Override
     public boolean isMCGlobal() {
-        return ((ipaddress[0] & 0xff) == 0xff
-                && (ipaddress[1] & 0x0f) == 0x0e);
+        return holder6.isMCGlobal();
     }
 
     /**
@@ -550,8 +756,7 @@
      */
     @Override
     public boolean isMCNodeLocal() {
-        return ((ipaddress[0] & 0xff) == 0xff
-                && (ipaddress[1] & 0x0f) == 0x01);
+        return holder6.isMCNodeLocal();
     }
 
     /**
@@ -564,8 +769,7 @@
      */
     @Override
     public boolean isMCLinkLocal() {
-        return ((ipaddress[0] & 0xff) == 0xff
-                && (ipaddress[1] & 0x0f) == 0x02);
+        return holder6.isMCLinkLocal();
     }
 
     /**
@@ -578,8 +782,7 @@
      */
     @Override
     public boolean isMCSiteLocal() {
-        return ((ipaddress[0] & 0xff) == 0xff
-                && (ipaddress[1] & 0x0f) == 0x05);
+        return holder6.isMCSiteLocal();
     }
 
     /**
@@ -593,10 +796,8 @@
      */
     @Override
     public boolean isMCOrgLocal() {
-        return ((ipaddress[0] & 0xff) == 0xff
-                && (ipaddress[1] & 0x0f) == 0x08);
+        return holder6.isMCOrgLocal();
     }
-
     /**
      * Returns the raw IP address of this <code>InetAddress</code>
      * object. The result is in network byte order: the highest order
@@ -606,7 +807,7 @@
      */
     @Override
     public byte[] getAddress() {
-        return ipaddress.clone();
+        return holder6.ipaddress.clone();
     }
 
     /**
@@ -617,7 +818,7 @@
      * @since 1.5
      */
      public int getScopeId () {
-        return scope_id;
+        return holder6.scope_id;
      }
 
     /**
@@ -628,7 +829,7 @@
      * @since 1.5
      */
      public NetworkInterface getScopedInterface () {
-        return scope_ifname;
+        return holder6.scope_ifname;
      }
 
     /**
@@ -641,13 +842,7 @@
      */
     @Override
     public String getHostAddress() {
-        String s = numericToTextFormat(ipaddress);
-        if (scope_ifname_set) { /* must check this first */
-            s = s + "%" + scope_ifname.getName();
-        } else if (scope_id_set) {
-            s = s + "%" + scope_id;
-        }
-        return s;
+        return holder6.getHostAddress();
     }
 
     /**
@@ -657,25 +852,7 @@
      */
     @Override
     public int hashCode() {
-        if (ipaddress != null) {
-
-            int hash = 0;
-            int i=0;
-            while (i<INADDRSZ) {
-                int j=0;
-                int component=0;
-                while (j<4 && i<INADDRSZ) {
-                    component = (component << 8) + ipaddress[i];
-                    j++;
-                    i++;
-                }
-                hash += component;
-            }
-            return hash;
-
-        } else {
-            return 0;
-        }
+        return holder6.hashCode();
     }
 
     /**
@@ -702,12 +879,7 @@
 
         Inet6Address inetAddr = (Inet6Address)obj;
 
-        for (int i = 0; i < INADDRSZ; i++) {
-            if (ipaddress[i] != inetAddr.ipaddress[i])
-                return false;
-        }
-
-        return true;
+        return holder6.equals(inetAddr.holder6);
     }
 
     /**
@@ -719,15 +891,7 @@
      * @since 1.4
      */
     public boolean isIPv4CompatibleAddress() {
-        if ((ipaddress[0] == 0x00) && (ipaddress[1] == 0x00) &&
-            (ipaddress[2] == 0x00) && (ipaddress[3] == 0x00) &&
-            (ipaddress[4] == 0x00) && (ipaddress[5] == 0x00) &&
-            (ipaddress[6] == 0x00) && (ipaddress[7] == 0x00) &&
-            (ipaddress[8] == 0x00) && (ipaddress[9] == 0x00) &&
-            (ipaddress[10] == 0x00) && (ipaddress[11] == 0x00))  {
-            return true;
-        }
-        return false;
+        return holder6.isIPv4CompatibleAddress();
     }
 
     // Utilities
@@ -757,23 +921,4 @@
      * Perform class load-time initializations.
      */
     private static native void init();
-
-    /**
-     * Following field is only used during (de)/serialization
-     */
-    private String ifname;
-
-    /**
-     * default behavior is overridden in order to write the
-     * scope_ifname field as a String, rather than a NetworkInterface
-     * which is not serializable
-     */
-    private synchronized void writeObject(java.io.ObjectOutputStream s)
-        throws IOException
-    {
-        if (scope_ifname_set) {
-            ifname = scope_ifname.getName();
-        }
-        s.defaultWriteObject();
-    }
 }
--- a/src/share/classes/java/net/InetAddress.java	Tue Jul 02 15:17:25 2013 -0700
+++ b/src/share/classes/java/net/InetAddress.java	Wed Jul 03 17:54:38 2013 +0100
@@ -213,6 +213,13 @@
             this.family = family;
         }
 
+        void init(String hostName, int family) {
+            this.hostName = hostName;
+            if (family != -1) {
+                this.family = family;
+            }
+        }
+
         String hostName;
 
         String getHostName() {
--- a/src/share/native/java/net/Inet6Address.c	Tue Jul 02 15:17:25 2013 -0700
+++ b/src/share/native/java/net/Inet6Address.c	Wed Jul 03 17:54:38 2013 +0100
@@ -33,6 +33,8 @@
  */
 
 jclass ia6_class;
+jfieldID ia6_holder6ID;
+
 jfieldID ia6_ipaddressID;
 jfieldID ia6_scopeidID;
 jfieldID ia6_cachedscopeidID;
@@ -48,21 +50,26 @@
  */
 JNIEXPORT void JNICALL
 Java_java_net_Inet6Address_init(JNIEnv *env, jclass cls) {
+    jclass ia6h_class;
     jclass c = (*env)->FindClass(env, "java/net/Inet6Address");
     CHECK_NULL(c);
     ia6_class = (*env)->NewGlobalRef(env, c);
     CHECK_NULL(ia6_class);
-    ia6_ipaddressID = (*env)->GetFieldID(env, ia6_class, "ipaddress", "[B");
+    ia6h_class = (*env)->FindClass(env, "java/net/Inet6Address$Inet6AddressHolder");
+    CHECK_NULL(ia6h_class);
+    ia6_holder6ID = (*env)->GetFieldID(env, ia6_class, "holder6", "Ljava/net/Inet6Address$Inet6AddressHolder;");
+    CHECK_NULL(ia6_holder6ID);
+    ia6_ipaddressID = (*env)->GetFieldID(env, ia6h_class, "ipaddress", "[B");
     CHECK_NULL(ia6_ipaddressID);
-    ia6_scopeidID = (*env)->GetFieldID(env, ia6_class, "scope_id", "I");
+    ia6_scopeidID = (*env)->GetFieldID(env, ia6h_class, "scope_id", "I");
     CHECK_NULL(ia6_scopeidID);
     ia6_cachedscopeidID = (*env)->GetFieldID(env, ia6_class, "cached_scope_id", "I");
     CHECK_NULL(ia6_cachedscopeidID);
-    ia6_scopeidsetID = (*env)->GetFieldID(env, ia6_class, "scope_id_set", "Z");
+    ia6_scopeidsetID = (*env)->GetFieldID(env, ia6h_class, "scope_id_set", "Z");
     CHECK_NULL(ia6_scopeidID);
-    ia6_scopeifnameID = (*env)->GetFieldID(env, ia6_class, "scope_ifname", "Ljava/net/NetworkInterface;");
+    ia6_scopeifnameID = (*env)->GetFieldID(env, ia6h_class, "scope_ifname", "Ljava/net/NetworkInterface;");
     CHECK_NULL(ia6_scopeifnameID);
-    ia6_scopeifnamesetID = (*env)->GetFieldID(env, ia6_class, "scope_ifname_set", "Z");
+    ia6_scopeifnamesetID = (*env)->GetFieldID(env, ia6h_class, "scope_ifname_set", "Z");
     CHECK_NULL(ia6_scopeifnamesetID);
     ia6_ctrID = (*env)->GetMethodID(env, ia6_class, "<init>", "()V");
     CHECK_NULL(ia6_ctrID);
--- a/src/share/native/java/net/net_util.c	Tue Jul 02 15:17:25 2013 -0700
+++ b/src/share/native/java/net/net_util.c	Wed Jul 03 17:54:38 2013 +0100
@@ -94,6 +94,111 @@
 extern jfieldID iac_addressID;
 extern jfieldID iac_familyID;
 
+/**
+ * set_ methods return JNI_TRUE on success JNI_FALSE on error
+ * get_ methods that return +ve int return -1 on error
+ * get_ methods that return objects return NULL on error.
+ */
+jobject getInet6Address_scopeifname(JNIEnv *env, jobject iaObj) {
+    jobject holder;
+
+    init(env);
+    holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
+    CHECK_NULL_RETURN(holder, NULL);
+    return (*env)->GetObjectField(env, holder, ia6_scopeifnameID);
+}
+
+int setInet6Address_scopeifname(JNIEnv *env, jobject iaObj, jobject scopeifname) {
+    jobject holder;
+
+    init(env);
+    holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
+    CHECK_NULL_RETURN(holder, JNI_FALSE);
+    (*env)->SetObjectField(env, holder, ia6_scopeifnameID, scopeifname);
+    return JNI_TRUE;
+}
+
+int getInet6Address_scopeifname_set(JNIEnv *env, jobject iaObj) {
+    jobject holder;
+
+    init(env);
+    holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
+    CHECK_NULL_RETURN(holder, -1);
+    return (*env)->GetBooleanField(env, holder, ia6_scopeifnamesetID);
+}
+
+int setInet6Address_scopeifname_set(JNIEnv *env, jobject iaObj, int scopeifname_set) {
+    jobject holder;
+
+    init(env);
+    holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
+    CHECK_NULL_RETURN(holder, JNI_FALSE);
+    (*env)->SetBooleanField(env, holder, ia6_scopeifnamesetID, scopeifname_set);
+    return JNI_TRUE;
+}
+
+int getInet6Address_scopeid_set(JNIEnv *env, jobject iaObj) {
+    jobject holder;
+
+    init(env);
+    holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
+    CHECK_NULL_RETURN(holder, -1);
+    return (*env)->GetBooleanField(env, holder, ia6_scopeidsetID);
+}
+
+int getInet6Address_scopeid(JNIEnv *env, jobject iaObj) {
+    jobject holder;
+
+    init(env);
+    holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
+    CHECK_NULL_RETURN(holder, -1);
+    return (*env)->GetIntField(env, holder, ia6_scopeidID);
+}
+
+int setInet6Address_scopeid(JNIEnv *env, jobject iaObj, int scopeid) {
+    jobject holder;
+
+    init(env);
+    holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
+    CHECK_NULL_RETURN(holder, JNI_FALSE);
+    (*env)->SetIntField(env, holder, ia6_scopeidID, scopeid);
+    if (scopeid > 0) {
+            (*env)->SetBooleanField(env, holder, ia6_scopeidsetID, JNI_TRUE);
+    }
+    return JNI_TRUE;
+}
+
+
+int getInet6Address_ipaddress(JNIEnv *env, jobject iaObj, char *dest) {
+    jobject holder, addr;
+    jbyteArray barr;
+
+    init(env);
+    holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
+    CHECK_NULL_RETURN(holder, JNI_FALSE);
+    addr =  (*env)->GetObjectField(env, holder, ia6_ipaddressID);
+    CHECK_NULL_RETURN(addr, JNI_FALSE);
+    (*env)->GetByteArrayRegion(env, addr, 0, 16, (jbyte *)dest);
+    return JNI_TRUE;
+}
+
+int setInet6Address_ipaddress(JNIEnv *env, jobject iaObj, char *address) {
+    jobject holder;
+    jbyteArray addr;
+
+    init(env);
+    holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
+    CHECK_NULL_RETURN(holder, JNI_FALSE);
+    addr =  (jbyteArray)(*env)->GetObjectField(env, holder, ia6_ipaddressID);
+    if (addr == NULL) {
+        addr = (*env)->NewByteArray(env, 16);
+        CHECK_NULL_RETURN(addr, JNI_FALSE);
+        (*env)->SetObjectField(env, holder, ia6_ipaddressID, addr);
+    }
+    (*env)->SetByteArrayRegion(env, addr, 0, 16, (jbyte *)address);
+    return JNI_TRUE;
+}
+
 void setInetAddress_addr(JNIEnv *env, jobject iaObj, int address) {
     jobject holder;
     init(env);
@@ -167,6 +272,7 @@
         } else {
             static jclass inet6Cls = 0;
             jint scope;
+            int ret;
             if (inet6Cls == 0) {
                 jclass c = (*env)->FindClass(env, "java/net/Inet6Address");
                 CHECK_NULL_RETURN(c, NULL);
@@ -176,18 +282,11 @@
             }
             iaObj = (*env)->NewObject(env, inet6Cls, ia6_ctrID);
             CHECK_NULL_RETURN(iaObj, NULL);
-            ipaddress = (*env)->NewByteArray(env, 16);
-            CHECK_NULL_RETURN(ipaddress, NULL);
-            (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
-                                       (jbyte *)&(him6->sin6_addr));
-
-            (*env)->SetObjectField(env, iaObj, ia6_ipaddressID, ipaddress);
-
+            ret = setInet6Address_ipaddress(env, iaObj, (char *)&(him6->sin6_addr));
+            CHECK_NULL_RETURN(ret, NULL);
             setInetAddress_family(env, iaObj, IPv6);
             scope = getScopeID(him);
-            (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
-            if (scope > 0)
-                (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
+            setInet6Address_scopeid(env, iaObj, scope);
         }
         *port = ntohs(him6->sin6_port);
     } else
@@ -247,9 +346,8 @@
             if (family == AF_INET) {
                 return JNI_FALSE;
             }
-            ipaddress = (*env)->GetObjectField(env, iaObj, ia6_ipaddressID);
-            scope = (*env)->GetIntField(env, iaObj, ia6_scopeidID);
-            (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddrCur);
+            scope = getInet6Address_scopeid(env, iaObj);
+            getInet6Address_ipaddress(env, iaObj, (char *)caddrCur);
             if (NET_IsEqual(caddrNew, caddrCur) && cmpScopeID(scope, him)) {
                 return JNI_TRUE;
             } else {
--- a/src/share/native/java/net/net_util.h	Tue Jul 02 15:17:25 2013 -0700
+++ b/src/share/native/java/net/net_util.h	Wed Jul 03 17:54:38 2013 +0100
@@ -58,6 +58,22 @@
 extern jfieldID iac_hostNameID;
 extern jfieldID ia_preferIPv6AddressID;
 
+/** (Inet6Address accessors)
+ * set_ methods return JNI_TRUE on success JNI_FALSE on error
+ * get_ methods that return int/boolean, return -1 on error
+ * get_ methods that return objects return NULL on error.
+ */
+extern jobject getInet6Address_scopeifname(JNIEnv *env, jobject ia6Obj);
+extern int setInet6Address_scopeifname(JNIEnv *env, jobject ia6Obj, jobject scopeifname);
+extern int getInet6Address_scopeifname_set(JNIEnv *env, jobject ia6Obj);
+extern int setInet6Address_scopeifname_set(JNIEnv *env, jobject ia6Obj,
+        int scopeifname_set);
+extern int getInet6Address_scopeid_set(JNIEnv *env, jobject ia6Obj);
+extern int getInet6Address_scopeid(JNIEnv *env, jobject ia6Obj);
+extern int setInet6Address_scopeid(JNIEnv *env, jobject ia6Obj, int scopeid);
+extern int getInet6Address_ipaddress(JNIEnv *env, jobject ia6Obj, char *dest);
+extern int setInet6Address_ipaddress(JNIEnv *env, jobject ia6Obj, char *address);
+
 extern void setInetAddress_addr(JNIEnv *env, jobject iaObj, int address);
 extern void setInetAddress_family(JNIEnv *env, jobject iaObj, int family);
 extern void setInetAddress_hostName(JNIEnv *env, jobject iaObj, jobject h);
@@ -93,6 +109,7 @@
 
 /* Inet6Address fields */
 extern jclass ia6_class;
+extern jfieldID ia6_holder6ID;
 extern jfieldID ia6_ipaddressID;
 extern jfieldID ia6_scopeidID;
 extern jfieldID ia6_cachedscopeidID;
--- a/src/solaris/native/java/net/Inet6AddressImpl.c	Tue Jul 02 15:17:25 2013 -0700
+++ b/src/solaris/native/java/net/Inet6AddressImpl.c	Wed Jul 03 17:54:38 2013 +0100
@@ -122,7 +122,6 @@
 static jclass ni_ia6cls;
 static jmethodID ni_ia4ctrID;
 static jmethodID ni_ia6ctrID;
-static jfieldID ni_ia6ipaddressID;
 static int initialized = 0;
 
 /*
@@ -158,7 +157,6 @@
       ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls);
       ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
       ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V");
-      ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B");
       initialized = 1;
     }
 
@@ -306,6 +304,7 @@
             }
 
             while (iterator != NULL) {
+              int ret1;
               if (iterator->ai_family == AF_INET) {
                 jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
                 if (IS_NULL(iaObj)) {
@@ -318,20 +317,17 @@
                 inetIndex++;
               } else if (iterator->ai_family == AF_INET6) {
                 jint scope = 0;
-                jbyteArray ipaddress;
 
                 jobject iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
                 if (IS_NULL(iaObj)) {
                   ret = NULL;
                   goto cleanupAndReturn;
                 }
-                ipaddress = (*env)->NewByteArray(env, 16);
-                if (IS_NULL(ipaddress)) {
-                  ret = NULL;
-                  goto cleanupAndReturn;
+                ret1 = setInet6Address_ipaddress(env, iaObj, (char *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
+                if (!ret1) {
+                    ret = NULL;
+                    goto cleanupAndReturn;
                 }
-                (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
-                                           (jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
 #ifdef __linux__
                 if (!kernelIsV22()) {
                   scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
@@ -340,10 +336,8 @@
                 scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
 #endif
                 if (scope != 0) { /* zero is default value, no need to set */
-                  (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
-                  (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
+                  setInet6Address_scopeid(env, iaObj, scope);
                 }
-                (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
                 setInetAddress_hostName(env, iaObj, host);
                 (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
                 inet6Index++;
--- a/src/solaris/native/java/net/NetworkInterface.c	Tue Jul 02 15:17:25 2013 -0700
+++ b/src/solaris/native/java/net/NetworkInterface.c	Wed Jul 03 17:54:38 2013 +0100
@@ -118,7 +118,6 @@
 static jmethodID ni_ia4ctrID;
 static jmethodID ni_ia6ctrID;
 static jmethodID ni_ibctrID;
-static jfieldID ni_ia6ipaddressID;
 static jfieldID ni_ibaddressID;
 static jfieldID ni_ib4broadcastID;
 static jfieldID ni_ib4maskID;
@@ -193,7 +192,6 @@
     ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
     ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V");
     ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V");
-    ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B");
     ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;");
     ni_ib4broadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;");
     ni_ib4maskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S");
@@ -332,11 +330,9 @@
 #ifdef AF_INET6
                 if (family == AF_INET6) {
                     jbyte *bytes = (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr);
-                    jbyteArray ipaddress = (*env)->GetObjectField(env, iaObj, ni_ia6ipaddressID);
                     jbyte caddr[16];
                     int i;
-
-                    (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddr);
+                    getInet6Address_ipaddress(env, iaObj, (char *)caddr);
                     i = 0;
                     while (i < 16) {
                         if (caddr[i] != bytes[i]) {
@@ -670,21 +666,17 @@
             int scope=0;
             iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
             if (iaObj) {
-                jbyteArray ipaddress = (*env)->NewByteArray(env, 16);
-                if (ipaddress == NULL) {
+                int ret = setInet6Address_ipaddress(env, iaObj, (char *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
+                if (ret == JNI_FALSE) {
                     return NULL;
                 }
-                (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
-                                                                        (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
 
                 scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id;
 
                 if (scope != 0) { /* zero is default value, no need to set */
-                    (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
-                    (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
-                    (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj);
+                    setInet6Address_scopeid(env, iaObj, scope);
+                    setInet6Address_scopeifname(env, iaObj, netifObj);
                 }
-                (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
             }
             ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
             if (ibObj) {
--- a/src/solaris/native/java/net/PlainDatagramSocketImpl.c	Tue Jul 02 15:17:25 2013 -0700
+++ b/src/solaris/native/java/net/PlainDatagramSocketImpl.c	Wed Jul 03 17:54:38 2013 +0100
@@ -2359,8 +2359,7 @@
             caddr[14] = ((address >> 8) & 0xff);
             caddr[15] = (address & 0xff);
         } else {
-            ipaddress = (*env)->GetObjectField(env, iaObj, ia6_ipaddressID);
-            (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddr);
+            getInet6Address_ipaddress(env, iaObj, caddr);
         }
 
         memcpy((void *)&(mname6.ipv6mr_multiaddr), caddr, sizeof(struct in6_addr));
--- a/src/solaris/native/java/net/net_util_md.c	Tue Jul 02 15:17:25 2013 -0700
+++ b/src/solaris/native/java/net/net_util_md.c	Wed Jul 03 17:54:38 2013 +0100
@@ -823,7 +823,6 @@
     /* needs work. 1. family 2. clean up him6 etc deallocate memory */
     if (ipv6_available() && !(family == IPv4 && v4MappedAddress == JNI_FALSE)) {
         struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
-        jbyteArray ipaddress;
         jbyte caddr[16];
         jint address;
 
@@ -844,8 +843,7 @@
                 caddr[15] = (address & 0xff);
             }
         } else {
-            ipaddress = (*env)->GetObjectField(env, iaObj, ia6_ipaddressID);
-            (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddr);
+            getInet6Address_ipaddress(env, iaObj, (char *)caddr);
         }
         memset((char *)him6, 0, sizeof(struct sockaddr_in6));
         him6->sin6_port = htons(port);
@@ -882,7 +880,7 @@
                  */
                 if (!cached_scope_id) {
                     if (ia6_scopeidID) {
-                        scope_id = (int)(*env)->GetIntField(env,iaObj,ia6_scopeidID);
+                        scope_id = getInet6Address_scopeid(env, iaObj);
                     }
                     if (scope_id != 0) {
                         /* check user-specified value for loopback case
@@ -928,7 +926,7 @@
 
         if (family != IPv4) {
             if (ia6_scopeidID) {
-                him6->sin6_scope_id = (int)(*env)->GetIntField(env, iaObj, ia6_scopeidID);
+                him6->sin6_scope_id = getInet6Address_scopeid(env, iaObj);
             }
         }
 #endif
--- a/src/windows/native/java/net/Inet6AddressImpl.c	Tue Jul 02 15:17:25 2013 -0700
+++ b/src/windows/native/java/net/Inet6AddressImpl.c	Wed Jul 03 17:54:38 2013 +0100
@@ -77,7 +77,6 @@
 static jclass ni_ia6cls;
 static jmethodID ni_ia4ctrID;
 static jmethodID ni_ia6ctrID;
-static jfieldID ni_ia6ipaddressID;
 static int initialized = 0;
 
 JNIEXPORT jobjectArray JNICALL
@@ -101,7 +100,6 @@
       ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls);
       ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
       ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V");
-      ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B");
       initialized = 1;
     }
     if (IS_NULL(host)) {
@@ -242,26 +240,22 @@
               (*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
                 inetIndex ++;
             } else if (iterator->ai_family == AF_INET6) {
-              jint scope = 0;
-              jbyteArray ipaddress;
+              jint scope = 0, ret1;
               jobject iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
               if (IS_NULL(iaObj)) {
                 ret = NULL;
                 goto cleanupAndReturn;
               }
-              ipaddress = (*env)->NewByteArray(env, 16);
-              if (IS_NULL(ipaddress)) {
+              ret1 = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
+
+              if (ret1 == JNI_FALSE) {
                 ret = NULL;
                 goto cleanupAndReturn;
               }
-              (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
-                                         (jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
               scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
               if (scope != 0) { /* zero is default value, no need to set */
-                (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
-                (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
+                setInet6Address_scopeid(env, iaObj, scope);
               }
-              (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
               setInetAddress_hostName(env, iaObj, host);
               (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
               inet6Index ++;
--- a/src/windows/native/java/net/NetworkInterface.c	Tue Jul 02 15:17:25 2013 -0700
+++ b/src/windows/native/java/net/NetworkInterface.c	Wed Jul 03 17:54:38 2013 +0100
@@ -72,8 +72,6 @@
 
 jclass ni_ia6cls;           /* Inet6Address */
 jmethodID ni_ia6ctrID;      /* Inet6Address() */
-jfieldID ni_ia6ipaddressID;
-jfieldID ni_ia6ipaddressID;
 
 jclass ni_ibcls;            /* InterfaceAddress */
 jmethodID ni_ibctrID;       /* InterfaceAddress() */
@@ -482,7 +480,6 @@
     ni_ia6cls = (*env)->FindClass(env, "java/net/Inet6Address");
     ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls);
     ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V");
-    ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B");
 
     ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress");
     ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls);
@@ -583,19 +580,16 @@
             int scope;
             iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
             if (iaObj) {
-                jbyteArray ipaddress = (*env)->NewByteArray(env, 16);
-                if (ipaddress == NULL) {
+                int ret = setInet6Address_ipaddress(env, iaObj,  (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr));
+                if (ret == JNI_FALSE) {
                     return NULL;
                 }
-                (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
-                    (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr));
+
                 scope = addrs->addr.him6.sin6_scope_id;
                 if (scope != 0) { /* zero is default value, no need to set */
-                    (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
-                    (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
-                    (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj);
+                    setInet6Address_scopeid(env, iaObj, scope);
+                    setInet6Address_scopeifname(env, iaObj, netifObj);
                 }
-                (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
                 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
                 if (ibObj == NULL) {
                   free_netaddr(netaddrP);
--- a/src/windows/native/java/net/NetworkInterface_winXP.c	Tue Jul 02 15:17:25 2013 -0700
+++ b/src/windows/native/java/net/NetworkInterface_winXP.c	Wed Jul 03 17:54:38 2013 +0100
@@ -499,19 +499,15 @@
             int scope;
             iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
             if (iaObj) {
-                jbyteArray ipaddress = (*env)->NewByteArray(env, 16);
-                if (ipaddress == NULL) {
+                int ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr));
+                if (ret == JNI_FALSE) {
                     return NULL;
                 }
-                (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
-                    (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr));
                 scope = addrs->addr.him6.sin6_scope_id;
                 if (scope != 0) { /* zero is default value, no need to set */
-                    (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
-                    (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
-                    (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj);
+                    setInet6Address_scopeid(env, iaObj, scope);
+                    setInet6Address_scopeifname(env, iaObj, netifObj);
                 }
-                (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
                 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
                 if (ibObj == NULL) {
                   free_netaddr(netaddrP);
--- a/src/windows/native/java/net/TwoStacksPlainSocketImpl.c	Tue Jul 02 15:17:25 2013 -0700
+++ b/src/windows/native/java/net/TwoStacksPlainSocketImpl.c	Wed Jul 03 17:54:38 2013 +0100
@@ -728,7 +728,6 @@
         setInetAddress_family(env, socketAddressObj, IPv4);
         (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
     } else {
-        jbyteArray addr;
         /* AF_INET6 -> Inet6Address */
         if (inet6Cls == 0) {
             jclass c = (*env)->FindClass(env, "java/net/Inet6Address");
@@ -751,10 +750,10 @@
             NET_SocketClose(fd);
             return;
         }
-        addr = (*env)->GetObjectField (env, socketAddressObj, ia6_ipaddressID);
-        (*env)->SetByteArrayRegion (env, addr, 0, 16, (const char *)&him.him6.sin6_addr);
+        setInet6Address_ipaddress(env, socketAddressObj, (const char *)&him.him6.sin6_addr);
+
         setInetAddress_family(env, socketAddressObj, IPv6);
-        (*env)->SetIntField(env, socketAddressObj, ia6_scopeidID, him.him6.sin6_scope_id);
+        setInet6Address_scopeid(env, socketAddressObj, him.him6.sin6_scope_id);
     }
     /* fields common to AF_INET and AF_INET6 */
 
--- a/test/java/net/Inet6Address/serialize/Serialize.java	Tue Jul 02 15:17:25 2013 -0700
+++ b/test/java/net/Inet6Address/serialize/Serialize.java	Wed Jul 03 17:54:38 2013 +0100
@@ -94,7 +94,26 @@
          } finally {
              ois.close();
          }
-         System.out.println(nobj);
+
+         nobj = (Inet6Address)InetAddress.getByAddress("foo.com", new byte[] {
+             (byte)0xfe,(byte)0x80,(byte)0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)0,
+             (byte)0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)1
+         });
+         if (!test1(nobj, addr1)) {
+             throw new RuntimeException("failed with " + nobj.toString());
+         }
+         nobj = (Inet6Address)InetAddress.getByAddress("x.bar.com", new byte[] {
+             (byte)0xfe,(byte)0xC0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)0,
+             (byte)0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)1
+         });
+         if (!test1(nobj, addr2)) {
+             throw new RuntimeException("failed with " + nobj.toString());
+         }
+         nobj = (Inet6Address)InetAddress.getByName("::1");
+         if (!test1(nobj, addr3)) {
+             throw new RuntimeException("failed with " + nobj.toString());
+         }
+
          System.out.println("All tests passed");
      }
 
@@ -113,4 +132,162 @@
              return false;
          }
      }
- }
+
+    static boolean test1 (Inet6Address obj, byte[] buf) throws Exception {
+         ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(buf));
+         Inet6Address nobj = (Inet6Address) ois.readObject();
+         ois.close();
+
+         if (nobj.equals(obj)) {
+             return true;
+         } else {
+             return false;
+         }
+    }
+
+    // Inet6Address instances serialized with JDK 6
+
+    static byte[] addr1 = {
+        (byte)0xac,(byte)0xed,(byte)0x00,(byte)0x05,(byte)0x73,(byte)0x72,
+        (byte)0x00,(byte)0x15,(byte)0x6a,(byte)0x61,(byte)0x76,(byte)0x61,
+        (byte)0x2e,(byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x2e,(byte)0x49,
+        (byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x36,(byte)0x41,(byte)0x64,
+        (byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73,(byte)0x73,(byte)0x5f,
+        (byte)0x7c,(byte)0x20,(byte)0x81,(byte)0x52,(byte)0x2c,(byte)0x80,
+        (byte)0x21,(byte)0x03,(byte)0x00,(byte)0x05,(byte)0x49,(byte)0x00,
+        (byte)0x08,(byte)0x73,(byte)0x63,(byte)0x6f,(byte)0x70,(byte)0x65,
+        (byte)0x5f,(byte)0x69,(byte)0x64,(byte)0x5a,(byte)0x00,(byte)0x0c,
+        (byte)0x73,(byte)0x63,(byte)0x6f,(byte)0x70,(byte)0x65,(byte)0x5f,
+        (byte)0x69,(byte)0x64,(byte)0x5f,(byte)0x73,(byte)0x65,(byte)0x74,
+        (byte)0x5a,(byte)0x00,(byte)0x10,(byte)0x73,(byte)0x63,(byte)0x6f,
+        (byte)0x70,(byte)0x65,(byte)0x5f,(byte)0x69,(byte)0x66,(byte)0x6e,
+        (byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x5f,(byte)0x73,(byte)0x65,
+        (byte)0x74,(byte)0x4c,(byte)0x00,(byte)0x06,(byte)0x69,(byte)0x66,
+        (byte)0x6e,(byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x74,(byte)0x00,
+        (byte)0x12,(byte)0x4c,(byte)0x6a,(byte)0x61,(byte)0x76,(byte)0x61,
+        (byte)0x2f,(byte)0x6c,(byte)0x61,(byte)0x6e,(byte)0x67,(byte)0x2f,
+        (byte)0x53,(byte)0x74,(byte)0x72,(byte)0x69,(byte)0x6e,(byte)0x67,
+        (byte)0x3b,(byte)0x5b,(byte)0x00,(byte)0x09,(byte)0x69,(byte)0x70,
+        (byte)0x61,(byte)0x64,(byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73,
+        (byte)0x73,(byte)0x74,(byte)0x00,(byte)0x02,(byte)0x5b,(byte)0x42,
+        (byte)0x78,(byte)0x72,(byte)0x00,(byte)0x14,(byte)0x6a,(byte)0x61,
+        (byte)0x76,(byte)0x61,(byte)0x2e,(byte)0x6e,(byte)0x65,(byte)0x74,
+        (byte)0x2e,(byte)0x49,(byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x41,
+        (byte)0x64,(byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73,(byte)0x73,
+        (byte)0x2d,(byte)0x9b,(byte)0x57,(byte)0xaf,(byte)0x9f,(byte)0xe3,
+        (byte)0xeb,(byte)0xdb,(byte)0x02,(byte)0x00,(byte)0x03,(byte)0x49,
+        (byte)0x00,(byte)0x07,(byte)0x61,(byte)0x64,(byte)0x64,(byte)0x72,
+        (byte)0x65,(byte)0x73,(byte)0x73,(byte)0x49,(byte)0x00,(byte)0x06,
+        (byte)0x66,(byte)0x61,(byte)0x6d,(byte)0x69,(byte)0x6c,(byte)0x79,
+        (byte)0x4c,(byte)0x00,(byte)0x08,(byte)0x68,(byte)0x6f,(byte)0x73,
+        (byte)0x74,(byte)0x4e,(byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x71,
+        (byte)0x00,(byte)0x7e,(byte)0x00,(byte)0x01,(byte)0x78,(byte)0x70,
+        (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
+        (byte)0x00,(byte)0x02,(byte)0x74,(byte)0x00,(byte)0x07,(byte)0x66,
+        (byte)0x6f,(byte)0x6f,(byte)0x2e,(byte)0x63,(byte)0x6f,(byte)0x6d,
+        (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
+        (byte)0x70,(byte)0x75,(byte)0x72,(byte)0x00,(byte)0x02,(byte)0x5b,
+        (byte)0x42,(byte)0xac,(byte)0xf3,(byte)0x17,(byte)0xf8,(byte)0x06,
+        (byte)0x08,(byte)0x54,(byte)0xe0,(byte)0x02,(byte)0x00,(byte)0x00,
+        (byte)0x78,(byte)0x70,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x10,
+        (byte)0xfe,(byte)0x80,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
+        (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
+        (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x01,(byte)0x78
+    };
+
+    static byte[] addr2 = {
+        (byte)0xac,(byte)0xed,(byte)0x00,(byte)0x05,(byte)0x73,(byte)0x72,
+        (byte)0x00,(byte)0x15,(byte)0x6a,(byte)0x61,(byte)0x76,(byte)0x61,
+        (byte)0x2e,(byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x2e,(byte)0x49,
+        (byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x36,(byte)0x41,(byte)0x64,
+        (byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73,(byte)0x73,(byte)0x5f,
+        (byte)0x7c,(byte)0x20,(byte)0x81,(byte)0x52,(byte)0x2c,(byte)0x80,
+        (byte)0x21,(byte)0x03,(byte)0x00,(byte)0x05,(byte)0x49,(byte)0x00,
+        (byte)0x08,(byte)0x73,(byte)0x63,(byte)0x6f,(byte)0x70,(byte)0x65,
+        (byte)0x5f,(byte)0x69,(byte)0x64,(byte)0x5a,(byte)0x00,(byte)0x0c,
+        (byte)0x73,(byte)0x63,(byte)0x6f,(byte)0x70,(byte)0x65,(byte)0x5f,
+        (byte)0x69,(byte)0x64,(byte)0x5f,(byte)0x73,(byte)0x65,(byte)0x74,
+        (byte)0x5a,(byte)0x00,(byte)0x10,(byte)0x73,(byte)0x63,(byte)0x6f,
+        (byte)0x70,(byte)0x65,(byte)0x5f,(byte)0x69,(byte)0x66,(byte)0x6e,
+        (byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x5f,(byte)0x73,(byte)0x65,
+        (byte)0x74,(byte)0x4c,(byte)0x00,(byte)0x06,(byte)0x69,(byte)0x66,
+        (byte)0x6e,(byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x74,(byte)0x00,
+        (byte)0x12,(byte)0x4c,(byte)0x6a,(byte)0x61,(byte)0x76,(byte)0x61,
+        (byte)0x2f,(byte)0x6c,(byte)0x61,(byte)0x6e,(byte)0x67,(byte)0x2f,
+        (byte)0x53,(byte)0x74,(byte)0x72,(byte)0x69,(byte)0x6e,(byte)0x67,
+        (byte)0x3b,(byte)0x5b,(byte)0x00,(byte)0x09,(byte)0x69,(byte)0x70,
+        (byte)0x61,(byte)0x64,(byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73,
+        (byte)0x73,(byte)0x74,(byte)0x00,(byte)0x02,(byte)0x5b,(byte)0x42,
+        (byte)0x78,(byte)0x72,(byte)0x00,(byte)0x14,(byte)0x6a,(byte)0x61,
+        (byte)0x76,(byte)0x61,(byte)0x2e,(byte)0x6e,(byte)0x65,(byte)0x74,
+        (byte)0x2e,(byte)0x49,(byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x41,
+        (byte)0x64,(byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73,(byte)0x73,
+        (byte)0x2d,(byte)0x9b,(byte)0x57,(byte)0xaf,(byte)0x9f,(byte)0xe3,
+        (byte)0xeb,(byte)0xdb,(byte)0x02,(byte)0x00,(byte)0x03,(byte)0x49,
+        (byte)0x00,(byte)0x07,(byte)0x61,(byte)0x64,(byte)0x64,(byte)0x72,
+        (byte)0x65,(byte)0x73,(byte)0x73,(byte)0x49,(byte)0x00,(byte)0x06,
+        (byte)0x66,(byte)0x61,(byte)0x6d,(byte)0x69,(byte)0x6c,(byte)0x79,
+        (byte)0x4c,(byte)0x00,(byte)0x08,(byte)0x68,(byte)0x6f,(byte)0x73,
+        (byte)0x74,(byte)0x4e,(byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x71,
+        (byte)0x00,(byte)0x7e,(byte)0x00,(byte)0x01,(byte)0x78,(byte)0x70,
+        (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
+        (byte)0x00,(byte)0x02,(byte)0x74,(byte)0x00,(byte)0x09,(byte)0x78,
+        (byte)0x2e,(byte)0x62,(byte)0x61,(byte)0x72,(byte)0x2e,(byte)0x63,
+        (byte)0x6f,(byte)0x6d,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
+        (byte)0x00,(byte)0x00,(byte)0x70,(byte)0x75,(byte)0x72,(byte)0x00,
+        (byte)0x02,(byte)0x5b,(byte)0x42,(byte)0xac,(byte)0xf3,(byte)0x17,
+        (byte)0xf8,(byte)0x06,(byte)0x08,(byte)0x54,(byte)0xe0,(byte)0x02,
+        (byte)0x00,(byte)0x00,(byte)0x78,(byte)0x70,(byte)0x00,(byte)0x00,
+        (byte)0x00,(byte)0x10,(byte)0xfe,(byte)0xc0,(byte)0x00,(byte)0x00,
+        (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
+        (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x01,
+        (byte)0x78
+    };
+
+    static byte[] addr3 = {
+        (byte)0xac,(byte)0xed,(byte)0x00,(byte)0x05,(byte)0x73,(byte)0x72,
+        (byte)0x00,(byte)0x15,(byte)0x6a,(byte)0x61,(byte)0x76,(byte)0x61,
+        (byte)0x2e,(byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x2e,(byte)0x49,
+        (byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x36,(byte)0x41,(byte)0x64,
+        (byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73,(byte)0x73,(byte)0x5f,
+        (byte)0x7c,(byte)0x20,(byte)0x81,(byte)0x52,(byte)0x2c,(byte)0x80,
+        (byte)0x21,(byte)0x03,(byte)0x00,(byte)0x05,(byte)0x49,(byte)0x00,
+        (byte)0x08,(byte)0x73,(byte)0x63,(byte)0x6f,(byte)0x70,(byte)0x65,
+        (byte)0x5f,(byte)0x69,(byte)0x64,(byte)0x5a,(byte)0x00,(byte)0x0c,
+        (byte)0x73,(byte)0x63,(byte)0x6f,(byte)0x70,(byte)0x65,(byte)0x5f,
+        (byte)0x69,(byte)0x64,(byte)0x5f,(byte)0x73,(byte)0x65,(byte)0x74,
+        (byte)0x5a,(byte)0x00,(byte)0x10,(byte)0x73,(byte)0x63,(byte)0x6f,
+        (byte)0x70,(byte)0x65,(byte)0x5f,(byte)0x69,(byte)0x66,(byte)0x6e,
+        (byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x5f,(byte)0x73,(byte)0x65,
+        (byte)0x74,(byte)0x4c,(byte)0x00,(byte)0x06,(byte)0x69,(byte)0x66,
+        (byte)0x6e,(byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x74,(byte)0x00,
+        (byte)0x12,(byte)0x4c,(byte)0x6a,(byte)0x61,(byte)0x76,(byte)0x61,
+        (byte)0x2f,(byte)0x6c,(byte)0x61,(byte)0x6e,(byte)0x67,(byte)0x2f,
+        (byte)0x53,(byte)0x74,(byte)0x72,(byte)0x69,(byte)0x6e,(byte)0x67,
+        (byte)0x3b,(byte)0x5b,(byte)0x00,(byte)0x09,(byte)0x69,(byte)0x70,
+        (byte)0x61,(byte)0x64,(byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73,
+        (byte)0x73,(byte)0x74,(byte)0x00,(byte)0x02,(byte)0x5b,(byte)0x42,
+        (byte)0x78,(byte)0x72,(byte)0x00,(byte)0x14,(byte)0x6a,(byte)0x61,
+        (byte)0x76,(byte)0x61,(byte)0x2e,(byte)0x6e,(byte)0x65,(byte)0x74,
+        (byte)0x2e,(byte)0x49,(byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x41,
+        (byte)0x64,(byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73,(byte)0x73,
+        (byte)0x2d,(byte)0x9b,(byte)0x57,(byte)0xaf,(byte)0x9f,(byte)0xe3,
+        (byte)0xeb,(byte)0xdb,(byte)0x02,(byte)0x00,(byte)0x03,(byte)0x49,
+        (byte)0x00,(byte)0x07,(byte)0x61,(byte)0x64,(byte)0x64,(byte)0x72,
+        (byte)0x65,(byte)0x73,(byte)0x73,(byte)0x49,(byte)0x00,(byte)0x06,
+        (byte)0x66,(byte)0x61,(byte)0x6d,(byte)0x69,(byte)0x6c,(byte)0x79,
+        (byte)0x4c,(byte)0x00,(byte)0x08,(byte)0x68,(byte)0x6f,(byte)0x73,
+        (byte)0x74,(byte)0x4e,(byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x71,
+        (byte)0x00,(byte)0x7e,(byte)0x00,(byte)0x01,(byte)0x78,(byte)0x70,
+        (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
+        (byte)0x00,(byte)0x02,(byte)0x70,(byte)0x00,(byte)0x00,(byte)0x00,
+        (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x70,(byte)0x75,(byte)0x72,
+        (byte)0x00,(byte)0x02,(byte)0x5b,(byte)0x42,(byte)0xac,(byte)0xf3,
+        (byte)0x17,(byte)0xf8,(byte)0x06,(byte)0x08,(byte)0x54,(byte)0xe0,
+        (byte)0x02,(byte)0x00,(byte)0x00,(byte)0x78,(byte)0x70,(byte)0x00,
+        (byte)0x00,(byte)0x00,(byte)0x10,(byte)0x00,(byte)0x00,(byte)0x00,
+        (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
+        (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
+        (byte)0x01,(byte)0x78
+    };
+}