< prev index next >

src/java.base/share/classes/java/io/PrintWriter.java

Print this page
@@ -29,10 +29,13 @@
  import java.util.Formatter;
  import java.util.Locale;
  import java.nio.charset.Charset;
  import java.nio.charset.IllegalCharsetNameException;
  import java.nio.charset.UnsupportedCharsetException;
+ import jdk.internal.access.JavaIOPrintWriterAccess;
+ import jdk.internal.access.SharedSecrets;
+ import jdk.internal.misc.InternalLock;
  
  /**
   * Prints formatted representations of objects to a text-output stream.  This
   * class implements all of the {@code print} methods found in {@link
   * PrintStream}.  It does not contain methods for writing raw bytes, for which

@@ -93,11 +96,11 @@
      /**
       * Creates a new PrintWriter, without automatic line flushing.
       *
       * @param  out        A character-output stream
       */
-     public PrintWriter (Writer out) {
+     public PrintWriter(Writer out) {
          this(out, false);
      }
  
      /**
       * Creates a new PrintWriter.

@@ -105,14 +108,12 @@
       * @param  out        A character-output stream
       * @param  autoFlush  A boolean; if true, the {@code println},
       *                    {@code printf}, or {@code format} methods will
       *                    flush the output buffer
       */
-     public PrintWriter(Writer out,
-                        boolean autoFlush) {
-         super(out);
-         this.out = out;
+     public PrintWriter(Writer out, boolean autoFlush) {
+         this.out = Objects.requireNonNull(out);
          this.autoFlush = autoFlush;
      }
  
      /**
       * Creates a new PrintWriter, without automatic line flushing, from an

@@ -390,17 +391,30 @@
      /**
       * Flushes the stream.
       * @see #checkError()
       */
      public void flush() {
-         try {
+         Object lock = this.lock;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 lockedFlush();
+             } finally {
+                 locker.unlock();
+             }
+         } else {
              synchronized (lock) {
-                 ensureOpen();
-                 out.flush();
+                 lockedFlush();
              }
          }
-         catch (IOException x) {
+     }
+ 
+     private void lockedFlush() {
+         try {
+             ensureOpen();
+             out.flush();
+         } catch (IOException x) {
              trouble = true;
          }
      }
  
      /**

@@ -408,19 +422,32 @@
       * with it. Closing a previously closed stream has no effect.
       *
       * @see #checkError()
       */
      public void close() {
-         try {
+         Object lock = this.lock;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 lockedClose();
+             } finally {
+                 locker.unlock();
+             }
+         } else {
              synchronized (lock) {
-                 if (out == null)
-                     return;
+                 lockedClose();
+             }
+         }
+     }
+ 
+     private void lockedClose() {
+         try {
+             if (out != null) {
                  out.close();
                  out = null;
              }
-         }
-         catch (IOException x) {
+         } catch (IOException x) {
              trouble = true;
          }
      }
  
      /**

@@ -474,20 +501,32 @@
      /**
       * Writes a single character.
       * @param c int specifying a character to be written.
       */
      public void write(int c) {
-         try {
+         Object lock = this.lock;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 lockedWrite(c);
+             } finally {
+                 locker.unlock();
+             }
+         } else {
              synchronized (lock) {
-                 ensureOpen();
-                 out.write(c);
+                 lockedWrite(c);
              }
          }
-         catch (InterruptedIOException x) {
+     }
+ 
+     private void lockedWrite(int c) {
+         try {
+             ensureOpen();
+             out.write(c);
+         } catch (InterruptedIOException x) {
              Thread.currentThread().interrupt();
-         }
-         catch (IOException x) {
+         } catch (IOException x) {
              trouble = true;
          }
      }
  
      /**

@@ -500,20 +539,32 @@
       *          If the values of the {@code off} and {@code len} parameters
       *          cause the corresponding method of the underlying {@code Writer}
       *          to throw an {@code IndexOutOfBoundsException}
       */
      public void write(char[] buf, int off, int len) {
-         try {
+         Object lock = this.lock;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 lockedWrite(buf, off, len);
+             } finally {
+                 locker.unlock();
+             }
+         } else {
              synchronized (lock) {
-                 ensureOpen();
-                 out.write(buf, off, len);
+                 lockedWrite(buf, off, len);
              }
          }
-         catch (InterruptedIOException x) {
+     }
+ 
+     private void lockedWrite(char[] buf, int off, int len) {
+         try {
+             ensureOpen();
+             out.write(buf, off, len);
+         } catch (InterruptedIOException x) {
              Thread.currentThread().interrupt();
-         }
-         catch (IOException x) {
+         } catch (IOException x) {
              trouble = true;
          }
      }
  
      /**

@@ -535,20 +586,32 @@
       *          If the values of the {@code off} and {@code len} parameters
       *          cause the corresponding method of the underlying {@code Writer}
       *          to throw an {@code IndexOutOfBoundsException}
       */
      public void write(String s, int off, int len) {
-         try {
+         Object lock = this.lock;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 lockedWrite(s, off, len);
+             } finally {
+                 locker.unlock();
+             }
+         } else {
              synchronized (lock) {
-                 ensureOpen();
-                 out.write(s, off, len);
+                 lockedWrite(s, off, len);
              }
          }
-         catch (InterruptedIOException x) {
+     }
+ 
+     private void lockedWrite(String s, int off, int len) {
+         try {
+             ensureOpen();
+             out.write(s, off, len);
+         } catch (InterruptedIOException x) {
              Thread.currentThread().interrupt();
-         }
-         catch (IOException x) {
+         } catch (IOException x) {
              trouble = true;
          }
      }
  
      /**

@@ -559,22 +622,34 @@
      public void write(String s) {
          write(s, 0, s.length());
      }
  
      private void newLine() {
-         try {
+         Object lock = this.lock;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 lockedNewLine();
+             } finally {
+                 locker.unlock();
+             }
+         } else {
              synchronized (lock) {
-                 ensureOpen();
-                 out.write(System.lineSeparator());
-                 if (autoFlush)
-                     out.flush();
+                 lockedNewLine();
              }
          }
-         catch (InterruptedIOException x) {
+     }
+ 
+     private void lockedNewLine() {
+         try {
+             ensureOpen();
+             out.write(System.lineSeparator());
+             if (autoFlush)
+                 out.flush();
+         } catch (InterruptedIOException x) {
              Thread.currentThread().interrupt();
-         }
-         catch (IOException x) {
+         } catch (IOException x) {
              trouble = true;
          }
      }
  
      /* Methods that do not terminate lines */

@@ -727,13 +802,24 @@
       * {@link #println()}.
       *
       * @param x the {@code boolean} value to be printed
       */
      public void println(boolean x) {
-         synchronized (lock) {
-             print(x);
-             println();
+         Object lock = this.lock;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 print(x);
+                 println();
+             } finally {
+                 locker.unlock();
+             }
+         } else {
+             synchronized (lock) {
+                 print(x);
+                 println();
+             }
          }
      }
  
      /**
       * Prints a character and then terminates the line.  This method behaves as

@@ -741,13 +827,24 @@
       * #println()}.
       *
       * @param x the {@code char} value to be printed
       */
      public void println(char x) {
-         synchronized (lock) {
-             print(x);
-             println();
+         Object lock = this.lock;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 print(x);
+                 println();
+             } finally {
+                 locker.unlock();
+             }
+         } else {
+             synchronized (lock) {
+                 print(x);
+                 println();
+             }
          }
      }
  
      /**
       * Prints an integer and then terminates the line.  This method behaves as

@@ -755,13 +852,24 @@
       * #println()}.
       *
       * @param x the {@code int} value to be printed
       */
      public void println(int x) {
-         synchronized (lock) {
-             print(x);
-             println();
+         Object lock = this.lock;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 print(x);
+                 println();
+             } finally {
+                 locker.unlock();
+             }
+         } else {
+             synchronized (lock) {
+                 print(x);
+                 println();
+             }
          }
      }
  
      /**
       * Prints a long integer and then terminates the line.  This method behaves

@@ -769,13 +877,24 @@
       * {@link #println()}.
       *
       * @param x the {@code long} value to be printed
       */
      public void println(long x) {
-         synchronized (lock) {
-             print(x);
-             println();
+         Object lock = this.lock;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 print(x);
+                 println();
+             } finally {
+                 locker.unlock();
+             }
+         } else {
+             synchronized (lock) {
+                 print(x);
+                 println();
+             }
          }
      }
  
      /**
       * Prints a floating-point number and then terminates the line.  This method

@@ -783,13 +902,24 @@
       * {@link #println()}.
       *
       * @param x the {@code float} value to be printed
       */
      public void println(float x) {
-         synchronized (lock) {
-             print(x);
-             println();
+         Object lock = this.lock;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 print(x);
+                 println();
+             } finally {
+                 locker.unlock();
+             }
+         } else {
+             synchronized (lock) {
+                 print(x);
+                 println();
+             }
          }
      }
  
      /**
       * Prints a double-precision floating-point number and then terminates the

@@ -797,13 +927,24 @@
       * #print(double)} and then {@link #println()}.
       *
       * @param x the {@code double} value to be printed
       */
      public void println(double x) {
-         synchronized (lock) {
-             print(x);
-             println();
+         Object lock = this.lock;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 print(x);
+                 println();
+             } finally {
+                 locker.unlock();
+             }
+         } else {
+             synchronized (lock) {
+                 print(x);
+                 println();
+             }
          }
      }
  
      /**
       * Prints an array of characters and then terminates the line.  This method

@@ -811,13 +952,24 @@
       * {@link #println()}.
       *
       * @param x the array of {@code char} values to be printed
       */
      public void println(char[] x) {
-         synchronized (lock) {
-             print(x);
-             println();
+         Object lock = this.lock;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 print(x);
+                 println();
+             } finally {
+                 locker.unlock();
+             }
+         } else {
+             synchronized (lock) {
+                 print(x);
+                 println();
+             }
          }
      }
  
      /**
       * Prints a String and then terminates the line.  This method behaves as

@@ -825,13 +977,24 @@
       * {@link #println()}.
       *
       * @param x the {@code String} value to be printed
       */
      public void println(String x) {
-         synchronized (lock) {
-             print(x);
-             println();
+         Object lock = this.lock;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 print(x);
+                 println();
+             } finally {
+                 locker.unlock();
+             }
+         } else {
+             synchronized (lock) {
+                 print(x);
+                 println();
+             }
          }
      }
  
      /**
       * Prints an Object and then terminates the line.  This method calls

@@ -842,13 +1005,24 @@
       *
       * @param x  The {@code Object} to be printed.
       */
      public void println(Object x) {
          String s = String.valueOf(x);
-         synchronized (lock) {
-             print(s);
-             println();
+         Object lock = this.lock;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 print(s);
+                 println();
+             } finally {
+                 locker.unlock();
+             }
+         } else {
+             synchronized (lock) {
+                 print(s);
+                 println();
+             }
          }
      }
  
      /**
       * A convenience method to write a formatted string to this writer using

@@ -990,26 +1164,40 @@
       * @return  This writer
       *
       * @since  1.5
       */
      public PrintWriter format(String format, Object ... args) {
-         try {
+         Object lock = this.lock;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 lockedFormat(format, args);
+             } finally {
+                 locker.unlock();
+             }
+         } else {
              synchronized (lock) {
-                 ensureOpen();
-                 if ((formatter == null)
-                     || (formatter.locale() != Locale.getDefault()))
-                     formatter = new Formatter(this);
-                 formatter.format(Locale.getDefault(), format, args);
-                 if (autoFlush)
-                     out.flush();
+                 lockedFormat(format, args);
              }
+         }
+         return this;
+     }
+ 
+     private void lockedFormat(String format, Object ... args) {
+         try {
+             ensureOpen();
+             if ((formatter == null)
+                 || (formatter.locale() != Locale.getDefault()))
+                 formatter = new Formatter(this);
+             formatter.format(Locale.getDefault(), format, args);
+             if (autoFlush)
+                 out.flush();
          } catch (InterruptedIOException x) {
              Thread.currentThread().interrupt();
          } catch (IOException x) {
              trouble = true;
          }
-         return this;
      }
  
      /**
       * Writes a formatted string to this writer using the specified format
       * string and arguments.  If automatic flushing is enabled, calls to this

@@ -1050,25 +1238,39 @@
       * @return  This writer
       *
       * @since  1.5
       */
      public PrintWriter format(Locale l, String format, Object ... args) {
-         try {
+         Object lock = this.lock;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 lockedFormat(l, format, args);
+             } finally {
+                 locker.unlock();
+             }
+         } else {
              synchronized (lock) {
-                 ensureOpen();
-                 if ((formatter == null) || (formatter.locale() != l))
-                     formatter = new Formatter(this, l);
-                 formatter.format(l, format, args);
-                 if (autoFlush)
-                     out.flush();
+                 lockedFormat(l, format, args);
              }
+         }
+         return this;
+     }
+ 
+     private void lockedFormat(Locale l, String format, Object ... args) {
+         try {
+             ensureOpen();
+             if ((formatter == null) || (formatter.locale() != l))
+                 formatter = new Formatter(this, l);
+             formatter.format(l, format, args);
+             if (autoFlush)
+                 out.flush();
          } catch (InterruptedIOException x) {
              Thread.currentThread().interrupt();
          } catch (IOException x) {
              trouble = true;
          }
-         return this;
      }
  
      /**
       * Appends the specified character sequence to this writer.
       *

@@ -1157,6 +1359,14 @@
       */
      public PrintWriter append(char c) {
          write(c);
          return this;
      }
+ 
+     static {
+         SharedSecrets.setJavaIOCPrintWriterAccess(new JavaIOPrintWriterAccess() {
+             public Object lock(PrintWriter pw) {
+                 return pw.lock;
+             }
+         });
+     }
  }
< prev index next >