--- a/src/java.base/share/classes/java/net/DatagramPacket.java Thu Oct 17 21:15:33 2019 +0100
+++ b/src/java.base/share/classes/java/net/DatagramPacket.java Fri Oct 18 17:08:59 2019 +0100
@@ -25,6 +25,9 @@
package java.net;
+import jdk.internal.access.JavaNetDatagramPacketAccess;
+import jdk.internal.access.SharedSecrets;
+
/**
* This class represents a datagram packet.
* <p>
@@ -367,12 +370,36 @@
* @since 1.1
*/
public synchronized void setLength(int length) {
+ setLengthField(length);
+ this.bufLength = this.length;
+ }
+
+ private synchronized void setLengthField(int length) {
if ((length + offset) > buf.length || length < 0 ||
- (length + offset) < 0) {
+ (length + offset) < 0) {
throw new IllegalArgumentException("illegal length");
}
this.length = length;
- this.bufLength = this.length;
+ }
+
+ private synchronized int getBufLength() {
+ return bufLength;
+ }
+
+ static {
+ SharedSecrets.setJavaNetDatagrtamPacketAccess(
+ new JavaNetDatagramPacketAccess() {
+ @Override
+ public int getBufLengthField(DatagramPacket packet) {
+ return packet.getBufLength();
+ }
+
+ @Override
+ public void setLengthField(DatagramPacket packet, int length) {
+ packet.setLengthField(length);
+ }
+ }
+ );
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/access/JavaNetDatagramPacketAccess.java Fri Oct 18 17:08:59 2019 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.access;
+
+import java.net.DatagramPacket;
+
+public interface JavaNetDatagramPacketAccess {
+ int getBufLengthField(DatagramPacket packet);
+ void setLengthField(DatagramPacket packet, int length);
+}
--- a/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java Thu Oct 17 21:15:33 2019 +0100
+++ b/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java Fri Oct 18 17:08:59 2019 +0100
@@ -64,6 +64,7 @@
private static JavaIORandomAccessFileAccess javaIORandomAccessFileAccess;
private static JavaObjectInputStreamAccess javaObjectInputStreamAccess;
private static JavaObjectInputFilterAccess javaObjectInputFilterAccess;
+ private static JavaNetDatagramPacketAccess javaNetDatagramPacketAccess;
private static JavaNetInetAddressAccess javaNetInetAddressAccess;
private static JavaNetHttpCookieAccess javaNetHttpCookieAccess;
private static JavaNetUriAccess javaNetUriAccess;
@@ -138,6 +139,16 @@
return javaLangReflectAccess;
}
+ public static void setJavaNetDatagrtamPacketAccess(JavaNetDatagramPacketAccess jndpa) {
+ javaNetDatagramPacketAccess = jndpa;
+ }
+
+ public static JavaNetDatagramPacketAccess getJavaNetDatagramPacketAccess() {
+ if (javaNetDatagramPacketAccess == null)
+ unsafe.ensureClassInitialized(java.net.DatagramPacket.class);
+ return javaNetDatagramPacketAccess;
+ }
+
public static void setJavaNetUriAccess(JavaNetUriAccess jnua) {
javaNetUriAccess = jnua;
}
--- a/src/java.base/share/classes/sun/nio/ch/NioDatagramSocketImpl.java Thu Oct 17 21:15:33 2019 +0100
+++ b/src/java.base/share/classes/sun/nio/ch/NioDatagramSocketImpl.java Fri Oct 18 17:08:59 2019 +0100
@@ -48,6 +48,8 @@
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
+import jdk.internal.access.JavaNetDatagramPacketAccess;
+import jdk.internal.access.SharedSecrets;
import jdk.internal.ref.CleanerFactory;
import sun.net.PlatformDatagramSocketImpl;
import sun.net.ResourceManager;
@@ -65,6 +67,9 @@
private static final NativeDispatcher nd = new SocketDispatcher();
+ private static final JavaNetDatagramPacketAccess DATAGRAM_PACKET_ACCESS =
+ SharedSecrets.getJavaNetDatagramPacketAccess();
+
private static final int MAX_PACKET_LEN = 65536;
private static final ProtocolFamily family = family();
@@ -410,7 +415,7 @@
Objects.requireNonNull(p);
byte[] b = p.getData();
int off = p.getOffset();
- int len = b.length - off;
+ int len = DATAGRAM_PACKET_ACCESS.getBufLengthField(p);
assert len >= 0;
if (len > MAX_PACKET_LEN)
len = MAX_PACKET_LEN;
@@ -441,7 +446,7 @@
p.setAddress(sender.getAddress());
if (p.getPort() != sender.getPort())
p.setPort(sender.getPort());
- p.setLength(n);
+ DATAGRAM_PACKET_ACCESS.setLengthField(p, n);
} catch (IOException e) {
// #### reset packet offset and length! ??
throw e;
--- a/test/jdk/java/net/DatagramPacket/ReuseBuf.java Thu Oct 17 21:15:33 2019 +0100
+++ b/test/jdk/java/net/DatagramPacket/ReuseBuf.java Fri Oct 18 17:08:59 2019 +0100
@@ -21,14 +21,16 @@
* questions.
*/
-/**
+/*
* @test
- *
* @bug 4424096
- *
* @summary DatagramPacket spec needs clarification (reuse buf)
+ * @run main ReuseBuf
+ * @run main/othervm -Djava.net.preferIPv4Stack=true ReuseBuf
+ * @run main/othervm -Djdk.net.usePlainDatagramSocketImpl=true ReuseBuf
*/
import java.net.*;
+import static java.lang.System.out;
public class ReuseBuf {
static String msgs[] = {"Hello World", "Java", "Good Bye"};
@@ -54,8 +56,12 @@
try {
ds.receive(dp);
String reply = new String(dp.getData(), dp.getOffset(), dp.getLength());
- ds.send(new DatagramPacket(reply.getBytes(),reply.length(),
- dp.getAddress(),dp.getPort()));
+ out.println("server: received [" + reply + "]");
+ for (int i=0; i<2; i++) {
+ out.println("server: sending [" + reply + "]");
+ ds.send(new DatagramPacket(reply.getBytes(), reply.length(),
+ dp.getAddress(), dp.getPort()));
+ }
if (reply.equals(msgs[msgs.length-1])) {
break;
}
@@ -76,16 +82,32 @@
byte b[] = new byte[100];
DatagramPacket dp = new DatagramPacket(b,b.length);
for (int i = 0; i < msgs.length; i++) {
+ out.println("client: sending [" + msgs[i] + "]");
ds.send(new DatagramPacket(msgs[i].getBytes(),msgs[i].length(),
InetAddress.getLocalHost(),
port));
ds.receive(dp);
- if (!msgs[i].equals(new String(dp.getData(), dp.getOffset(), dp.getLength()))) {
- throw new RuntimeException("Msg expected: "+msgs[i] +msgs[i].length()+
- "msg received: "+new String(dp.getData(), dp.getOffset(), dp.getLength())+dp.getLength());
+ String recvmsg = new String(dp.getData(), dp.getOffset(), dp.getLength());
+ out.println("client: received [" + recvmsg + "]");
+ if (!msgs[i].equals(recvmsg)) {
+ throw new RuntimeException("Msg expected: " + msgs[i] +
+ ", msg received: " + recvmsg);
+ }
+
+ byte ba[] = new byte[1];
+ DatagramPacket dp2 = new DatagramPacket(ba, ba.length);
+ dp2.setData(new byte[99], 5, 3); // only 3 bytes
+ ds.receive(dp2);
+ String expectedMsg = msgs[i].substring(0, 3);
+ recvmsg = new String(dp2.getData(), dp2.getOffset(), dp2.getLength());
+ out.println("client: received [" + recvmsg + "]");
+ if (!expectedMsg.equals(recvmsg)) {
+ throw new RuntimeException("Msg truncated expected: " + expectedMsg +
+ ", msg received: "+ recvmsg);
}
}
ds.close();
- System.out.println("Test Passed!!!");
+ out.println("Test Passed!!!");
+ st.join();
}
}