--- a/make/sun/net/FILES_java.gmk Fri Jan 28 20:01:23 2011 +0300
+++ b/make/sun/net/FILES_java.gmk Mon Jan 31 06:47:56 2011 -0800
@@ -34,6 +34,7 @@ FILES_java = \
sun/net/ProgressEvent.java \
sun/net/ProgressListener.java \
sun/net/ProgressMeteringPolicy.java \
+ sun/net/ResourceManager.java \
sun/net/TelnetInputStream.java \
sun/net/TelnetOutputStream.java \
sun/net/TelnetProtocolException.java \
--- a/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Fri Jan 28 20:01:23 2011 +0300
+++ b/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Mon Jan 31 06:47:56 2011 -0800
@@ -28,6 +28,7 @@ import java.io.IOException;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.Enumeration;
+import sun.net.ResourceManager;
/**
* Abstract datagram and multicast socket implementation base class.
@@ -65,8 +66,15 @@ abstract class AbstractPlainDatagramSock
* Creates a datagram socket
*/
protected synchronized void create() throws SocketException {
+ ResourceManager.beforeUdpCreate();
fd = new FileDescriptor();
- datagramSocketCreate();
+ try {
+ datagramSocketCreate();
+ } catch (SocketException ioe) {
+ ResourceManager.afterUdpClose();
+ fd = null;
+ throw ioe;
+ }
}
/**
@@ -211,6 +219,7 @@ abstract class AbstractPlainDatagramSock
protected void close() {
if (fd != null) {
datagramSocketClose();
+ ResourceManager.afterUdpClose();
fd = null;
}
}
--- a/src/share/classes/java/net/AbstractPlainSocketImpl.java Fri Jan 28 20:01:23 2011 +0300
+++ b/src/share/classes/java/net/AbstractPlainSocketImpl.java Mon Jan 31 06:47:56 2011 -0800
@@ -33,6 +33,7 @@ import java.io.ByteArrayOutputStream;
import java.io.ByteArrayOutputStream;
import sun.net.ConnectionResetException;
+import sun.net.ResourceManager;
/**
* Default Socket Implementation. This implementation does
@@ -69,6 +70,10 @@ abstract class AbstractPlainSocketImpl e
private int resetState;
private Object resetLock = new Object();
+ /* whether this Socket is a stream (TCP) socket or not (UDP)
+ */
+ private boolean stream;
+
/**
* Load net library into runtime.
*/
@@ -83,7 +88,19 @@ abstract class AbstractPlainSocketImpl e
*/
protected synchronized void create(boolean stream) throws IOException {
fd = new FileDescriptor();
- socketCreate(stream);
+ this.stream = stream;
+ if (!stream) {
+ ResourceManager.beforeUdpCreate();
+ try {
+ socketCreate(false);
+ } catch (IOException ioe) {
+ ResourceManager.afterUdpClose();
+ fd = null;
+ throw ioe;
+ }
+ } else {
+ socketCreate(true);
+ }
if (socket != null)
socket.setCreated();
if (serverSocket != null)
@@ -458,6 +475,9 @@ abstract class AbstractPlainSocketImpl e
protected void close() throws IOException {
synchronized(fdLock) {
if (fd != null) {
+ if (!stream) {
+ ResourceManager.afterUdpClose();
+ }
if (fdUseCount == 0) {
if (closePending) {
return;
--- a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java Fri Jan 28 20:01:23 2011 +0300
+++ b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java Mon Jan 31 06:47:56 2011 -0800
@@ -32,6 +32,7 @@ import java.nio.channels.*;
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.lang.ref.SoftReference;
+import sun.net.ResourceManager;
/**
@@ -98,9 +99,15 @@ class DatagramChannelImpl
throws IOException
{
super(sp);
- this.fd = Net.socket(false);
- this.fdVal = IOUtil.fdVal(fd);
- this.state = ST_UNCONNECTED;
+ ResourceManager.beforeUdpCreate();
+ try {
+ this.fd = Net.socket(false);
+ this.fdVal = IOUtil.fdVal(fd);
+ this.state = ST_UNCONNECTED;
+ } catch (IOException ioe) {
+ ResourceManager.afterUdpClose();
+ throw ioe;
+ }
}
public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd)
@@ -587,6 +594,7 @@ class DatagramChannelImpl
protected void implCloseSelectableChannel() throws IOException {
synchronized (stateLock) {
nd.preClose(fd);
+ ResourceManager.afterUdpClose();
long th;
if ((th = readerThread) != 0)
NativeThread.signal(th);
--- a/src/share/classes/sun/nio/ch/Net.java Fri Jan 28 20:01:23 2011 +0300
+++ b/src/share/classes/sun/nio/ch/Net.java Mon Jan 31 06:47:56 2011 -0800
@@ -111,7 +111,7 @@ class Net {
// -- Socket operations --
- static FileDescriptor socket(boolean stream) {
+ static FileDescriptor socket(boolean stream) throws IOException {
return IOUtil.newFD(socket0(stream, false));
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/net/ResourceManager.java Mon Jan 31 06:47:56 2011 -0800
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011, 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 sun.net;
+
+import java.net.SocketException;
+import java.util.concurrent.atomic.AtomicInteger;
+import sun.security.action.GetPropertyAction;
+
+/**
+ * Manages count of total number of UDP sockets and ensures
+ * that exception is thrown if we try to create more than the
+ * configured limit.
+ *
+ * This functionality could be put in NetHooks some time in future.
+ */
+
+public class ResourceManager {
+
+ /* default maximum number of udp sockets per VM
+ * when a security manager is enabled.
+ * The default is 1024 which is high enough to be useful
+ * but low enough to be well below the maximum number
+ * of port numbers actually available on all OSes for
+ * such sockets (5000 on some versions of windows)
+ */
+
+ private static final int DEFAULT_MAX_SOCKETS = 1024;
+ private static final int maxSockets;
+ private static final AtomicInteger numSockets;
+
+ static {
+ String prop = java.security.AccessController.doPrivileged(
+ new GetPropertyAction("sun.net.maxDatagramSockets")
+ );
+ int defmax = DEFAULT_MAX_SOCKETS;
+ try {
+ if (prop != null) {
+ defmax = Integer.parseInt(prop);
+ }
+ } catch (NumberFormatException e) {}
+ maxSockets = defmax;
+ numSockets = new AtomicInteger(0);
+ }
+
+ public static void beforeUdpCreate() throws SocketException {
+ if (System.getSecurityManager() != null) {
+ if (numSockets.incrementAndGet() > maxSockets) {
+ numSockets.decrementAndGet();
+ throw new SocketException("maximum number of DatagramSockets reached");
+ }
+ }
+ }
+
+ public static void afterUdpClose() {
+ if (System.getSecurityManager() != null) {
+ numSockets.decrementAndGet();
+ }
+ }
+}