diff --git a/src/share/classes/java/net/SocketInputStream.java b/src/share/classes/java/net/SocketInputStream.java index 41b18bdc7e0c3c9370ed0796d76822d2e48676a8..f9a50a06de9c6eff28de387e035df1f07537f5ff 100644 --- a/src/share/classes/java/net/SocketInputStream.java +++ b/src/share/classes/java/net/SocketInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2016, 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 @@ -155,11 +155,12 @@ class SocketInputStream extends FileInputStream } // bounds check - if (length <= 0 || off < 0 || off + length > b.length) { + if (length <= 0 || off < 0 || length > b.length - off) { if (length == 0) { return 0; } - throw new ArrayIndexOutOfBoundsException(); + throw new ArrayIndexOutOfBoundsException("length == " + length + + " off == " + off + " buffer length == " + b.length); } boolean gotReset = false; diff --git a/src/share/classes/java/net/SocketOutputStream.java b/src/share/classes/java/net/SocketOutputStream.java index 2404e9583f438a500da26e85a260126925324308..20a63e61373e4e00d90b86f51ae941431c79fa60 100644 --- a/src/share/classes/java/net/SocketOutputStream.java +++ b/src/share/classes/java/net/SocketOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2016, 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 @@ -97,11 +97,13 @@ class SocketOutputStream extends FileOutputStream */ private void socketWrite(byte b[], int off, int len) throws IOException { - if (len <= 0 || off < 0 || off + len > b.length) { + + if (len <= 0 || off < 0 || len > b.length - off) { if (len == 0) { return; } - throw new ArrayIndexOutOfBoundsException(); + throw new ArrayIndexOutOfBoundsException("len == " + len + + " off == " + off + " buffer length == " + b.length); } FileDescriptor fd = impl.acquireFD(); diff --git a/src/solaris/native/java/net/SocketOutputStream.c b/src/solaris/native/java/net/SocketOutputStream.c index d6e01ffa1a27654e4377ce18bf2a355518334956..16d68c2a34775bb764b229904114e9d2b9a43d8f 100644 --- a/src/solaris/native/java/net/SocketOutputStream.c +++ b/src/solaris/native/java/net/SocketOutputStream.c @@ -103,31 +103,35 @@ Java_java_net_SocketOutputStream_socketWrite0(JNIEnv *env, jobject this, int llen = chunkLen; (*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP); - while(llen > 0) { - int n = NET_Send(fd, bufP + loff, llen, 0); - if (n > 0) { - llen -= n; - loff += n; - continue; - } - if (n == JVM_IO_INTR) { - JNU_ThrowByName(env, "java/io/InterruptedIOException", 0); - } else { - if (errno == ECONNRESET) { - JNU_ThrowByName(env, "sun/net/ConnectionResetException", - "Connection reset"); + if ((*env)->ExceptionCheck(env)) { + break; + } else { + while(llen > 0) { + int n = NET_Send(fd, bufP + loff, llen, 0); + if (n > 0) { + llen -= n; + loff += n; + continue; + } + if (n == JVM_IO_INTR) { + JNU_ThrowByName(env, "java/io/InterruptedIOException", 0); } else { - NET_ThrowByNameWithLastError(env, "java/net/SocketException", - "Write failed"); + if (errno == ECONNRESET) { + JNU_ThrowByName(env, "sun/net/ConnectionResetException", + "Connection reset"); + } else { + NET_ThrowByNameWithLastError(env, "java/net/SocketException", + "Write failed"); + } } + if (bufP != BUF) { + free(bufP); + } + return; } - if (bufP != BUF) { - free(bufP); - } - return; + len -= chunkLen; + off += chunkLen; } - len -= chunkLen; - off += chunkLen; } if (bufP != BUF) { diff --git a/src/windows/native/java/net/SocketOutputStream.c b/src/windows/native/java/net/SocketOutputStream.c index 4bcfbc32434ffa913eb1d0a01cc5176d67a0e24c..daec5203c510c117deeb0dc18ba9db34bc397d8f 100644 --- a/src/windows/native/java/net/SocketOutputStream.c +++ b/src/windows/native/java/net/SocketOutputStream.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -100,66 +100,69 @@ Java_java_net_SocketOutputStream_socketWrite0(JNIEnv *env, jobject this, int retry = 0; (*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP); - - while(llen > 0) { - int n = send(fd, bufP + loff, llen, 0); - if (n > 0) { - llen -= n; - loff += n; - continue; - } - - /* - * Due to a bug in Windows Sockets (observed on NT and Windows - * 2000) it may be necessary to retry the send. The issue is that - * on blocking sockets send/WSASend is supposed to block if there - * is insufficient buffer space available. If there are a large - * number of threads blocked on write due to congestion then it's - * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS. - * The workaround we use is to retry the send. If we have a - * large buffer to send (>2k) then we retry with a maximum of - * 2k buffer. If we hit the issue with <=2k buffer then we backoff - * for 1 second and retry again. We repeat this up to a reasonable - * limit before bailing out and throwing an exception. In load - * conditions we've observed that the send will succeed after 2-3 - * attempts but this depends on network buffers associated with - * other sockets draining. - */ - if (WSAGetLastError() == WSAENOBUFS) { - if (llen > MAX_BUFFER_LEN) { - buflen = MAX_BUFFER_LEN; - chunkLen = MAX_BUFFER_LEN; - llen = MAX_BUFFER_LEN; + if ((*env)->ExceptionCheck(env)) { + break; + } else { + while(llen > 0) { + int n = send(fd, bufP + loff, llen, 0); + if (n > 0) { + llen -= n; + loff += n; continue; } - if (retry >= 30) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "No buffer space available - exhausted attempts to queue buffer"); - if (bufP != BUF) { - free(bufP); + + /* + * Due to a bug in Windows Sockets (observed on NT and Windows + * 2000) it may be necessary to retry the send. The issue is that + * on blocking sockets send/WSASend is supposed to block if there + * is insufficient buffer space available. If there are a large + * number of threads blocked on write due to congestion then it's + * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS. + * The workaround we use is to retry the send. If we have a + * large buffer to send (>2k) then we retry with a maximum of + * 2k buffer. If we hit the issue with <=2k buffer then we backoff + * for 1 second and retry again. We repeat this up to a reasonable + * limit before bailing out and throwing an exception. In load + * conditions we've observed that the send will succeed after 2-3 + * attempts but this depends on network buffers associated with + * other sockets draining. + */ + if (WSAGetLastError() == WSAENOBUFS) { + if (llen > MAX_BUFFER_LEN) { + buflen = MAX_BUFFER_LEN; + chunkLen = MAX_BUFFER_LEN; + llen = MAX_BUFFER_LEN; + continue; + } + if (retry >= 30) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "No buffer space available - exhausted attempts to queue buffer"); + if (bufP != BUF) { + free(bufP); + } + return; } - return; + Sleep(1000); + retry++; + continue; } - Sleep(1000); - retry++; - continue; - } - /* - * Send failed - can be caused by close or write error. - */ - if (WSAGetLastError() == WSAENOTSOCK) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); - } else { - NET_ThrowCurrent(env, "socket write error"); - } - if (bufP != BUF) { - free(bufP); + /* + * Send failed - can be caused by close or write error. + */ + if (WSAGetLastError() == WSAENOTSOCK) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + } else { + NET_ThrowCurrent(env, "socket write error"); + } + if (bufP != BUF) { + free(bufP); + } + return; } - return; + len -= chunkLen; + off += chunkLen; } - len -= chunkLen; - off += chunkLen; } if (bufP != BUF) {