78
78
*/
79
79
public class ServerSocket implements java .io .Closeable {
80
80
/**
81
- * Various states of this socket.
81
+ * The underlying SocketImpl
82
82
*/
83
- private boolean created = false ;
84
- private boolean bound = false ;
85
- private boolean closed = false ;
86
- private Object closeLock = new Object ();
83
+ private final SocketImpl impl ;
87
84
88
85
/**
89
- * The implementation of this Socket .
86
+ * Various states of this socket, need stateLock to change .
90
87
*/
91
- private SocketImpl impl ;
88
+ private volatile boolean created ; // impl.create(boolean) called
89
+ private volatile boolean bound ;
90
+ private volatile boolean closed ;
91
+ private final Object stateLock = new Object ();
92
92
93
93
/**
94
94
* Creates a server socket with a user-specified {@code SocketImpl}.
@@ -124,7 +124,7 @@ private static Void checkPermission() {
124
124
* @revised 1.4
125
125
*/
126
126
public ServerSocket () throws IOException {
127
- setImpl ();
127
+ this . impl = createImpl ();
128
128
}
129
129
130
130
/**
@@ -264,18 +264,15 @@ public ServerSocket(int port, int backlog) throws IOException {
264
264
* @since 1.1
265
265
*/
266
266
public ServerSocket (int port , int backlog , InetAddress bindAddr ) throws IOException {
267
- setImpl ();
268
267
if (port < 0 || port > 0xFFFF )
269
- throw new IllegalArgumentException (
270
- "Port value out of range: " + port );
268
+ throw new IllegalArgumentException ("Port value out of range: " + port );
271
269
if (backlog < 1 )
272
- backlog = 50 ;
270
+ backlog = 50 ;
271
+
272
+ this .impl = createImpl ();
273
273
try {
274
274
bind (new InetSocketAddress (bindAddr , port ), backlog );
275
- } catch (SecurityException e ) {
276
- close ();
277
- throw e ;
278
- } catch (IOException e ) {
275
+ } catch (IOException | SecurityException e ) {
279
276
close ();
280
277
throw e ;
281
278
}
@@ -289,35 +286,36 @@ public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOExcept
289
286
* @throws SocketException if creation fails.
290
287
* @since 1.4
291
288
*/
292
- SocketImpl getImpl () throws SocketException {
293
- if (!created )
294
- createImpl ();
289
+ private SocketImpl getImpl () throws SocketException {
290
+ if (!created ) {
291
+ synchronized (stateLock ) {
292
+ if (!created ) {
293
+ if (closed ) {
294
+ throw new SocketException ("Socket is closed" );
295
+ }
296
+ try {
297
+ impl .create (true );
298
+ } catch (SocketException e ) {
299
+ throw e ;
300
+ } catch (IOException e ) {
301
+ throw new SocketException (e .getMessage ());
302
+ }
303
+ created = true ;
304
+ }
305
+ }
306
+ }
295
307
return impl ;
296
308
}
297
309
298
- private void setImpl () {
310
+ /**
311
+ * Create a SocketImpl for a server socket.
312
+ */
313
+ private static SocketImpl createImpl () {
299
314
SocketImplFactory factory = ServerSocket .factory ;
300
315
if (factory != null ) {
301
- impl = factory .createSocketImpl ();
316
+ return factory .createSocketImpl ();
302
317
} else {
303
- impl = SocketImpl .createPlatformSocketImpl (true );
304
- }
305
- }
306
-
307
- /**
308
- * Creates the socket implementation.
309
- *
310
- * @throws SocketException if creation fails
311
- * @since 1.4
312
- */
313
- void createImpl () throws SocketException {
314
- if (impl == null )
315
- setImpl ();
316
- try {
317
- impl .create (true );
318
- created = true ;
319
- } catch (IOException e ) {
320
- throw new SocketException (e .getMessage ());
318
+ return SocketImpl .createPlatformSocketImpl (true );
321
319
}
322
320
}
323
321
@@ -379,21 +377,21 @@ public void bind(SocketAddress endpoint, int backlog) throws IOException {
379
377
if (epoint .isUnresolved ())
380
378
throw new SocketException ("Unresolved address" );
381
379
if (backlog < 1 )
382
- backlog = 50 ;
383
- try {
384
- @ SuppressWarnings ("removal" )
385
- SecurityManager security = System .getSecurityManager ();
386
- if (security != null )
387
- security .checkListen (epoint .getPort ());
380
+ backlog = 50 ;
381
+
382
+ @ SuppressWarnings ("removal" )
383
+ SecurityManager security = System .getSecurityManager ();
384
+ if (security != null )
385
+ security .checkListen (epoint .getPort ());
386
+
387
+ synchronized (stateLock ) {
388
+ if (closed )
389
+ throw new SocketException ("Socket is closed" );
390
+ if (bound )
391
+ throw new SocketException ("Already bound" );
388
392
getImpl ().bind (epoint .getAddress (), epoint .getPort ());
389
393
getImpl ().listen (backlog );
390
394
bound = true ;
391
- } catch (SecurityException e ) {
392
- bound = false ;
393
- throw e ;
394
- } catch (IOException e ) {
395
- bound = false ;
396
- throw e ;
397
395
}
398
396
}
399
397
@@ -711,12 +709,18 @@ private void ensureCompatible(SocketImpl si) throws IOException {
711
709
* @revised 1.4
712
710
*/
713
711
public void close () throws IOException {
714
- synchronized (closeLock ) {
715
- if (isClosed ())
716
- return ;
717
- if (created )
718
- impl .close ();
719
- closed = true ;
712
+ synchronized (stateLock ) {
713
+ if (!closed ) {
714
+ try {
715
+ // close underlying socket if created
716
+ if (created ) {
717
+ impl .close ();
718
+ }
719
+ } finally {
720
+ closed = true ;
721
+ }
722
+
723
+ }
720
724
}
721
725
}
722
726
@@ -760,9 +764,7 @@ public boolean isBound() {
760
764
* @since 1.4
761
765
*/
762
766
public boolean isClosed () {
763
- synchronized (closeLock ) {
764
- return closed ;
765
- }
767
+ return closed ;
766
768
}
767
769
768
770
/**
@@ -783,7 +785,7 @@ public boolean isClosed() {
783
785
* @since 1.1
784
786
* @see #getSoTimeout()
785
787
*/
786
- public synchronized void setSoTimeout (int timeout ) throws SocketException {
788
+ public void setSoTimeout (int timeout ) throws SocketException {
787
789
if (isClosed ())
788
790
throw new SocketException ("Socket is closed" );
789
791
if (timeout < 0 )
@@ -799,7 +801,7 @@ public synchronized void setSoTimeout(int timeout) throws SocketException {
799
801
* @since 1.1
800
802
* @see #setSoTimeout(int)
801
803
*/
802
- public synchronized int getSoTimeout () throws IOException {
804
+ public int getSoTimeout () throws IOException {
803
805
if (isClosed ())
804
806
throw new SocketException ("Socket is closed" );
805
807
Object o = getImpl ().getOption (SocketOptions .SO_TIMEOUT );
@@ -984,7 +986,7 @@ public static synchronized void setSocketFactory(SocketImplFactory fac) throws I
984
986
* @since 1.4
985
987
* @see #getReceiveBufferSize
986
988
*/
987
- public synchronized void setReceiveBufferSize (int size ) throws SocketException {
989
+ public void setReceiveBufferSize (int size ) throws SocketException {
988
990
if (!(size > 0 )) {
989
991
throw new IllegalArgumentException ("negative receive size" );
990
992
}
@@ -1007,8 +1009,7 @@ public synchronized void setReceiveBufferSize (int size) throws SocketException
1007
1009
* @see #setReceiveBufferSize(int)
1008
1010
* @since 1.4
1009
1011
*/
1010
- public synchronized int getReceiveBufferSize ()
1011
- throws SocketException {
1012
+ public int getReceiveBufferSize () throws SocketException {
1012
1013
if (isClosed ())
1013
1014
throw new SocketException ("Socket is closed" );
1014
1015
int result = 0 ;
0 commit comments