# HG changeset patch
# User robm
# Date 1352819613 0
# Node ID 46582c3c96b3fdd43b58761c3869ce55fad1c755
# Parent ee4632a30696050ebd5c014fb3da64112ab48dd3
7201071: InetSocketAddress serialization issue
Reviewed-by: chegar
diff --git a/src/share/classes/java/net/InetSocketAddress.java b/src/share/classes/java/net/InetSocketAddress.java
--- jdk/src/share/classes/java/net/InetSocketAddress.java
+++ jdk/src/share/classes/java/net/InetSocketAddress.java
@@ -24,9 +24,12 @@
*/
package java.net;
-import java.io.ObjectInputStream;
import java.io.IOException;
import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
+import java.io.ObjectStreamField;
/**
*
@@ -46,24 +49,106 @@ import java.io.InvalidObjectException;
* @see java.net.ServerSocket
* @since 1.4
*/
-public class InetSocketAddress extends SocketAddress {
- /* The hostname of the Socket Address
- * @serial
- */
- private String hostname = null;
- /* The IP address of the Socket Address
- * @serial
- */
- private InetAddress addr = null;
- /* The port number of the Socket Address
- * @serial
- */
- private int port;
+public class InetSocketAddress
+ extends SocketAddress
+{
+ // Private implementation class pointed to by all public methods.
+ private static class InetSocketAddressHolder {
+ // The hostname of the Socket Address
+ private String hostname;
+ // The IP address of the Socket Address
+ private InetAddress addr;
+ // The port number of the Socket Address
+ private int port;
+
+ private InetSocketAddressHolder(String hostname, InetAddress addr, int port) {
+ this.hostname = hostname;
+ this.addr = addr;
+ this.port = port;
+ }
+
+ private int getPort() {
+ return port;
+ }
+
+ private InetAddress getAddress() {
+ return addr;
+ }
+
+ private String getHostName() {
+ if (hostname != null)
+ return hostname;
+ if (addr != null)
+ return addr.getHostName();
+ return null;
+ }
+
+ private String getHostString() {
+ if (hostname != null)
+ return hostname;
+ if (addr != null) {
+ if (addr.hostName != null)
+ return addr.hostName;
+ else
+ return addr.getHostAddress();
+ }
+ return null;
+ }
+
+ private boolean isUnresolved() {
+ return addr == null;
+ }
+
+ @Override
+ public String toString() {
+ if (isUnresolved()) {
+ return hostname + ":" + port;
+ } else {
+ return addr.toString() + ":" + port;
+ }
+ }
+
+ @Override
+ public final boolean equals(Object obj) {
+ if (obj == null || !(obj instanceof InetSocketAddressHolder))
+ return false;
+ InetSocketAddressHolder that = (InetSocketAddressHolder)obj;
+ boolean sameIP;
+ if (addr != null)
+ sameIP = addr.equals(that.addr);
+ else if (hostname != null)
+ sameIP = (that.addr == null) &&
+ hostname.equalsIgnoreCase(that.hostname);
+ else
+ sameIP = (that.addr == null) && (that.hostname == null);
+ return sameIP && (port == that.port);
+ }
+
+ @Override
+ public final int hashCode() {
+ if (addr != null)
+ return addr.hashCode() + port;
+ if (hostname != null)
+ return hostname.toLowerCase().hashCode() + port;
+ return port;
+ }
+ }
+
+ private final transient InetSocketAddressHolder holder;
private static final long serialVersionUID = 5076001401234631237L;
- private InetSocketAddress() {
+ private static int checkPort(int port) {
+ if (port < 0 || port > 0xFFFF)
+ throw new IllegalArgumentException("port out of range:" + port);
+ return port;
}
+
+ private static String checkHost(String hostname) {
+ if (hostname == null)
+ throw new IllegalArgumentException("hostname can't be null");
+ return hostname;
+ }
/**
* Creates a socket address where the IP address is the wildcard address
@@ -97,14 +182,10 @@ public class InetSocketAddress extends S
* range of valid port values.
*/
public InetSocketAddress(InetAddress addr, int port) {
- if (port < 0 || port > 0xFFFF) {
- throw new IllegalArgumentException("port out of range:" + port);
- }
- this.port = port;
- if (addr == null)
- this.addr = InetAddress.anyLocalAddress();
- else
- this.addr = addr;
+ holder = new InetSocketAddressHolder(
+ null,
+ addr == null ? InetAddress.anyLocalAddress() : addr,
+ checkPort(port));
}
/**
@@ -132,19 +213,20 @@ public class InetSocketAddress extends S
* @see #isUnresolved()
*/
public InetSocketAddress(String hostname, int port) {
- if (port < 0 || port > 0xFFFF) {
- throw new IllegalArgumentException("port out of range:" + port);
- }
- if (hostname == null) {
- throw new IllegalArgumentException("hostname can't be null");
- }
+ checkHost(hostname);
+ InetAddress addr = null;
+ String host = null;
try {
addr = InetAddress.getByName(hostname);
} catch(UnknownHostException e) {
- this.hostname = hostname;
- addr = null;
+ host = hostname;
}
- this.port = port;
+ holder = new InetSocketAddressHolder(host, addr, checkPort(port));
+ }
+
+ // private constructor for creating unresolved instances
+ private InetSocketAddress(int port, String hostname) {
+ holder = new InetSocketAddressHolder(hostname, null, port);
}
/**
@@ -169,31 +251,67 @@ public class InetSocketAddress extends S
* @since 1.5
*/
public static InetSocketAddress createUnresolved(String host, int port) {
- if (port < 0 || port > 0xFFFF) {
- throw new IllegalArgumentException("port out of range:" + port);
- }
- if (host == null) {
- throw new IllegalArgumentException("hostname can't be null");
- }
- InetSocketAddress s = new InetSocketAddress();
- s.port = port;
- s.hostname = host;
- s.addr = null;
- return s;
+ return new InetSocketAddress(checkPort(port), checkHost(host));
+ }
+
+ /**
+ * @serialField hostname String
+ * @serialField addr InetAddress
+ * @serialField port int
+ */
+ private static final ObjectStreamField[] serialPersistentFields = {
+ new ObjectStreamField("hostname", String.class),
+ new ObjectStreamField("addr", InetAddress.class),
+ new ObjectStreamField("port", int.class)};
+
+ private void writeObject(ObjectOutputStream out)
+ throws IOException
+ {
+ // Don't call defaultWriteObject()
+ ObjectOutputStream.PutField pfields = out.putFields();
+ pfields.put("hostname", holder.hostname);
+ pfields.put("addr", holder.addr);
+ pfields.put("port", holder.port);
+ out.writeFields();
}
- private void readObject(ObjectInputStream s)
- throws IOException, ClassNotFoundException {
- s.defaultReadObject();
+ private void readObject(ObjectInputStream in)
+ throws IOException, ClassNotFoundException
+ {
+ // Don't call defaultReadObject()
+ ObjectInputStream.GetField oisFields = in.readFields();
+ final String oisHostname = (String)oisFields.get("hostname", null);
+ final InetAddress oisAddr = (InetAddress)oisFields.get("addr", null);
+ final int oisPort = oisFields.get("port", -1);
// Check that our invariants are satisfied
- if (port < 0 || port > 0xFFFF) {
- throw new InvalidObjectException("port out of range:" + port);
- }
-
- if (hostname == null && addr == null) {
+ checkPort(oisPort);
+ if (oisHostname == null && oisAddr == null)
throw new InvalidObjectException("hostname and addr " +
"can't both be null");
+
+ InetSocketAddressHolder h = new InetSocketAddressHolder(oisHostname,
+ oisAddr,
+ oisPort);
+ UNSAFE.putObject(this, FIELDS_OFFSET, h);
+ }
+
+ private void readObjectNoData()
+ throws ObjectStreamException
+ {
+ throw new InvalidObjectException("Stream data required");
+ }
+
+ 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(
+ InetSocketAddress.class.getDeclaredField("holder"));
+ UNSAFE = unsafe;
+ } catch (NoSuchFieldException e) {
+ throw new Error(e);
}
}
@@ -203,7 +321,7 @@ public class InetSocketAddress extends S
* @return the port number.
*/
public final int getPort() {
- return port;
+ return holder.getPort();
}
/**
@@ -213,7 +331,7 @@ public class InetSocketAddress extends S
* @return the InetAdress or null
if it is unresolved.
*/
public final InetAddress getAddress() {
- return addr;
+ return holder.getAddress();
}
/**
@@ -222,11 +340,7 @@ public class InetSocketAddress extends S
* @return the hostname part of the address.
*/
public final String getHostName() {
- if (hostname != null)
- return hostname;
- if (addr != null)
- return addr.getHostName();
- return null;
+ return holder.getHostName();
}
/**
@@ -238,15 +352,7 @@ public class InetSocketAddress extends S
* @since 1.6
*/
final String getHostString() {
- if (hostname != null)
- return hostname;
- if (addr != null) {
- if (addr.hostName != null)
- return addr.hostName;
- else
- return addr.getHostAddress();
- }
- return null;
+ return holder.getHostString();
}
/**
@@ -256,7 +362,7 @@ public class InetSocketAddress extends S
* an InetAddress
.
*/
public final boolean isUnresolved() {
- return addr == null;
+ return holder.isUnresolved();
}
/**
@@ -267,12 +373,9 @@ public class InetSocketAddress extends S
*
* @return a string representation of this object.
*/
+ @Override
public String toString() {
- if (isUnresolved()) {
- return hostname + ":" + port;
- } else {
- return addr.toString() + ":" + port;
- }
+ return holder.toString();
}
/**
@@ -295,16 +398,7 @@ public class InetSocketAddress extends S
public final boolean equals(Object obj) {
if (obj == null || !(obj instanceof InetSocketAddress))
return false;
- InetSocketAddress sockAddr = (InetSocketAddress) obj;
- boolean sameIP = false;
- if (this.addr != null)
- sameIP = this.addr.equals(sockAddr.addr);
- else if (this.hostname != null)
- sameIP = (sockAddr.addr == null) &&
- this.hostname.equals(sockAddr.hostname);
- else
- sameIP = (sockAddr.addr == null) && (sockAddr.hostname == null);
- return sameIP && (this.port == sockAddr.port);
+ return holder.equals(((InetSocketAddress) obj).holder);
}
/**
@@ -312,11 +406,8 @@ public class InetSocketAddress extends S
*
* @return a hash code value for this socket address.
*/
+ @Override
public final int hashCode() {
- if (addr != null)
- return addr.hashCode() + port;
- if (hostname != null)
- return hostname.hashCode() + port;
- return port;
+ return holder.hashCode();
}
}
diff --git a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java
--- jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java
+++ jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java
@@ -239,7 +239,7 @@ class DatagramChannelImpl
synchronized (writeLock) {
ensureOpen();
- InetSocketAddress isa = (InetSocketAddress)target;
+ InetSocketAddress isa = Net.checkAddress(target);
InetAddress ia = isa.getAddress();
if (ia == null)
throw new IOException("Target address not resolved");
@@ -250,9 +250,9 @@ class DatagramChannelImpl
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
if (ia.isMulticastAddress()) {
- sm.checkMulticast(isa.getAddress());
+ sm.checkMulticast(ia);
} else {
- sm.checkConnect(isa.getAddress().getHostAddress(),
+ sm.checkConnect(ia.getHostAddress(),
isa.getPort());
}
}
@@ -272,7 +272,7 @@ class DatagramChannelImpl
return 0;
writerThread = NativeThread.current();
do {
- n = send(fd, src, target);
+ n = send(fd, src, isa);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(n);
} finally {
@@ -283,7 +283,7 @@ class DatagramChannelImpl
}
}
- private int send(FileDescriptor fd, ByteBuffer src, SocketAddress target)
+ private int send(FileDescriptor fd, ByteBuffer src, InetSocketAddress target)
throws IOException
{
if (src instanceof DirectBuffer)
@@ -315,7 +315,7 @@ class DatagramChannelImpl
}
private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
- SocketAddress target)
+ InetSocketAddress target)
throws IOException
{
int pos = bb.position();
@@ -324,7 +324,7 @@ class DatagramChannelImpl
int rem = (pos <= lim ? lim - pos : 0);
int written = send0(fd, ((DirectBuffer)bb).address() + pos,
- rem, target);
+ rem, target.getAddress(), target.getPort());
if (written > 0)
bb.position(pos + written);
return written;
@@ -703,8 +703,8 @@ class DatagramChannelImpl
boolean connected)
throws IOException;
- private native int send0(FileDescriptor fd, long address, int len,
- SocketAddress sa)
+ private native int send0(FileDescriptor fd, long address,
+ int len, InetAddress addr, int port)
throws IOException;
static {
diff --git a/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c b/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c
--- jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c
+++ jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c
@@ -46,8 +46,6 @@
#include "sun_nio_ch_DatagramChannelImpl.h"
-static jfieldID isa_addrID; /* address in java.net.InetSocketAddress */
-static jfieldID isa_portID; /* port in java.net.InetSocketAddress */
static jfieldID dci_senderID; /* sender in sun.nio.ch.DatagramChannelImpl */
static jfieldID dci_senderAddrID; /* sender InetAddress in sun.nio.ch.DatagramChannelImpl */
static jfieldID dci_senderPortID; /* sender port in sun.nio.ch.DatagramChannelImpl */
@@ -61,9 +59,6 @@ Java_sun_nio_ch_DatagramChannelImpl_init
isa_class = (*env)->NewGlobalRef(env, clazz);
isa_ctorID = (*env)->GetMethodID(env, clazz, "",
"(Ljava/net/InetAddress;I)V");
- isa_addrID = (*env)->GetFieldID(env, clazz, "addr",
- "Ljava/net/InetAddress;");
- isa_portID = (*env)->GetFieldID(env, clazz, "port", "I");
clazz = (*env)->FindClass(env, "sun/nio/ch/DatagramChannelImpl");
dci_senderID = (*env)->GetFieldID(env, clazz, "sender",
@@ -198,16 +193,15 @@ Java_sun_nio_ch_DatagramChannelImpl_rece
JNIEXPORT jint JNICALL
Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this,
- jobject fdo, jlong address,
- jint len, jobject dest)
+ jobject fdo, jlong address,
+ jint len, jobject destAddress,
+ jint destPort)
{
jint fd = fdval(env, fdo);
void *buf = (void *)jlong_to_ptr(address);
SOCKADDR sa;
int sa_len = SOCKADDR_LEN;
jint n = 0;
- jobject destAddress = (*env)->GetObjectField(env, dest, isa_addrID);
- jint destPort = (*env)->GetIntField(env, dest, isa_portID);
if (len > MAX_PACKET_LEN) {
len = MAX_PACKET_LEN;
diff --git a/src/windows/native/sun/nio/ch/DatagramChannelImpl.c b/src/windows/native/sun/nio/ch/DatagramChannelImpl.c
--- jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c
+++ jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c
@@ -34,8 +34,6 @@
#include "net_util.h"
#include
-static jfieldID isa_addrID; /* address in java.net.InetSocketAddress */
-static jfieldID isa_portID; /* port in java.net.InetSocketAddress */
static jfieldID dci_senderID; /* sender in sun.nio.ch.DatagramChannelImpl */
static jfieldID dci_senderAddrID; /* sender InetAddress in sun.nio.ch.DatagramChannelImpl */
static jfieldID dci_senderPortID; /* sender port in sun.nio.ch.DatagramChannelImpl */
@@ -87,9 +85,6 @@ Java_sun_nio_ch_DatagramChannelImpl_init
isa_class = (*env)->NewGlobalRef(env, clazz);
isa_ctorID = (*env)->GetMethodID(env, clazz, "",
"(Ljava/net/InetAddress;I)V");
- isa_addrID = (*env)->GetFieldID(env, clazz, "addr",
- "Ljava/net/InetAddress;");
- isa_portID = (*env)->GetFieldID(env, clazz, "port", "I");
clazz = (*env)->FindClass(env, "sun/nio/ch/DatagramChannelImpl");
dci_senderID = (*env)->GetFieldID(env, clazz, "sender",
@@ -268,17 +263,14 @@ Java_sun_nio_ch_DatagramChannelImpl_rece
JNIEXPORT jint JNICALL
Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this,
- jobject fdo, jlong address,
- jint len, jobject dest)
+ jobject fdo, jlong address, jint len,
+ jobject destAddress, jint destPort)
{
jint fd = fdval(env, fdo);
void *buf = (void *)jlong_to_ptr(address);
SOCKETADDRESS psa;
int sa_len = sizeof(psa);
jint rv = 0;
- jobject destAddress = (*env)->GetObjectField(env, dest, isa_addrID);
- jint destPort = (*env)->GetIntField(env, dest, isa_portID);
-
if (NET_InetAddressToSockaddr(env, destAddress, destPort,
(struct sockaddr *)&psa,
diff --git a/test/java/nio/channels/DatagramChannel/SendToUnresolved.java b/test/java/nio/channels/DatagramChannel/SendToUnresolved.java
--- jdk/test/java/nio/channels/DatagramChannel/SendToUnresolved.java
+++ jdk/test/java/nio/channels/DatagramChannel/SendToUnresolved.java
@@ -44,6 +44,8 @@ public class SendToUnresolved {
throw new RuntimeException("Expected exception not thrown");
} catch (IOException e) {
// Correct result
+ } catch (UnresolvedAddressException e) {
+ // Correct result
}
dc.close();
}