From cbaf8947ef80ea5cc9bd894034b65895fa639955 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Tue, 12 Nov 2024 09:38:00 -0800 Subject: [PATCH 1/8] 8343039: Remove jdk.internal.misc.InternalLock and usages from java.io --- .../classes/java/io/BufferedInputStream.java | 135 +----- .../classes/java/io/BufferedOutputStream.java | 67 +-- .../share/classes/java/io/BufferedReader.java | 395 +++++++----------- .../share/classes/java/io/BufferedWriter.java | 201 +++------ .../classes/java/io/InputStreamReader.java | 25 +- .../classes/java/io/OutputStreamWriter.java | 25 +- .../share/classes/java/io/PrintStream.java | 323 ++++---------- .../share/classes/java/io/PrintWriter.java | 395 ++++-------------- .../classes/java/io/PushbackInputStream.java | 41 +- .../share/classes/java/io/Reader.java | 52 +-- .../share/classes/java/io/Writer.java | 76 +--- 11 files changed, 428 insertions(+), 1307 deletions(-) diff --git a/src/java.base/share/classes/java/io/BufferedInputStream.java b/src/java.base/share/classes/java/io/BufferedInputStream.java index c401873ce12e4..d3b706f468562 100644 --- a/src/java.base/share/classes/java/io/BufferedInputStream.java +++ b/src/java.base/share/classes/java/io/BufferedInputStream.java @@ -28,7 +28,6 @@ import java.util.Arrays; import java.util.Objects; -import jdk.internal.misc.InternalLock; import jdk.internal.misc.Unsafe; import jdk.internal.util.ArraysSupport; @@ -74,9 +73,6 @@ public class BufferedInputStream extends FilterInputStream { private static final long BUF_OFFSET = U.objectFieldOffset(BufferedInputStream.class, "buf"); - // initialized to null when BufferedInputStream is sub-classed - private final InternalLock lock; - // initial buffer size (DEFAULT_BUFFER_SIZE or size specified to constructor) private final int initialSize; @@ -242,21 +238,13 @@ public BufferedInputStream(InputStream in, int size) { throw new IllegalArgumentException("Buffer size <= 0"); } initialSize = size; - if (getClass() == BufferedInputStream.class) { - // use internal lock and lazily create buffer when not subclassed - lock = InternalLock.newLockOrNull(); - buf = EMPTY; - } else { - // use monitors and eagerly create buffer when subclassed - lock = null; - buf = new byte[size]; - } + buf = new byte[size]; } /** * Fills the buffer with more data, taking into account * shuffling and other tricks for dealing with marks. - * Assumes that it is being called by a locked method. + * Assumes that it is being called by a synchronized method. * This method also assumes that all data has already been read in, * hence pos > count. */ @@ -310,22 +298,7 @@ else if (pos >= buffer.length) { /* no room left in buffer */ * or an I/O error occurs. * @see java.io.FilterInputStream#in */ - public int read() throws IOException { - if (lock != null) { - lock.lock(); - try { - return implRead(); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - return implRead(); - } - } - } - - private int implRead() throws IOException { + public synchronized int read() throws IOException { if (pos >= count) { fill(); if (pos >= count) @@ -397,22 +370,7 @@ private int read1(byte[] b, int off, int len) throws IOException { * or an I/O error occurs. * @throws IndexOutOfBoundsException {@inheritDoc} */ - public int read(byte[] b, int off, int len) throws IOException { - if (lock != null) { - lock.lock(); - try { - return implRead(b, off, len); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - return implRead(b, off, len); - } - } - } - - private int implRead(byte[] b, int off, int len) throws IOException { + public synchronized int read(byte[] b, int off, int len) throws IOException { ensureOpen(); if ((off | len | (off + len) | (b.length - (off + len))) < 0) { throw new IndexOutOfBoundsException(); @@ -444,22 +402,7 @@ private int implRead(byte[] b, int off, int len) throws IOException { * {@code in.skip(n)} throws an IOException, * or an I/O error occurs. */ - public long skip(long n) throws IOException { - if (lock != null) { - lock.lock(); - try { - return implSkip(n); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - return implSkip(n); - } - } - } - - private long implSkip(long n) throws IOException { + public synchronized long skip(long n) throws IOException { ensureOpen(); if (n <= 0) { return 0; @@ -500,22 +443,7 @@ private long implSkip(long n) throws IOException { * invoking its {@link #close()} method, * or an I/O error occurs. */ - public int available() throws IOException { - if (lock != null) { - lock.lock(); - try { - return implAvailable(); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - return implAvailable(); - } - } - } - - private int implAvailable() throws IOException { + public synchronized int available() throws IOException { int n = count - pos; int avail = getInIfOpen().available(); return n > (Integer.MAX_VALUE - avail) @@ -531,22 +459,7 @@ private int implAvailable() throws IOException { * the mark position becomes invalid. * @see java.io.BufferedInputStream#reset() */ - public void mark(int readlimit) { - if (lock != null) { - lock.lock(); - try { - implMark(readlimit); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implMark(readlimit); - } - } - } - - private void implMark(int readlimit) { + public synchronized void mark(int readlimit) { marklimit = readlimit; markpos = pos; } @@ -567,22 +480,7 @@ private void implMark(int readlimit) { * method, or an I/O error occurs. * @see java.io.BufferedInputStream#mark(int) */ - public void reset() throws IOException { - if (lock != null) { - lock.lock(); - try { - implReset(); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implReset(); - } - } - } - - private void implReset() throws IOException { + public synchronized void reset() throws IOException { ensureOpen(); if (markpos < 0) throw new IOException("Resetting to invalid mark"); @@ -628,23 +526,8 @@ public void close() throws IOException { } @Override - public long transferTo(OutputStream out) throws IOException { + public synchronized long transferTo(OutputStream out) throws IOException { Objects.requireNonNull(out, "out"); - if (lock != null) { - lock.lock(); - try { - return implTransferTo(out); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - return implTransferTo(out); - } - } - } - - private long implTransferTo(OutputStream out) throws IOException { if (getClass() == BufferedInputStream.class && markpos == -1) { int avail = count - pos; if (avail > 0) { diff --git a/src/java.base/share/classes/java/io/BufferedOutputStream.java b/src/java.base/share/classes/java/io/BufferedOutputStream.java index 687f0c91bc4f7..be01baf64462c 100644 --- a/src/java.base/share/classes/java/io/BufferedOutputStream.java +++ b/src/java.base/share/classes/java/io/BufferedOutputStream.java @@ -26,7 +26,6 @@ package java.io; import java.util.Arrays; -import jdk.internal.misc.InternalLock; import jdk.internal.misc.VM; /** @@ -47,9 +46,6 @@ public class BufferedOutputStream extends FilterOutputStream { private static final int DEFAULT_INITIAL_BUFFER_SIZE = 512; private static final int DEFAULT_MAX_BUFFER_SIZE = 8192; - // initialized to null when BufferedOutputStream is sub-classed - private final InternalLock lock; - /** * The internal buffer where data is stored. */ @@ -89,15 +85,7 @@ private BufferedOutputStream(OutputStream out, int initialSize, int maxSize) { throw new IllegalArgumentException("Buffer size <= 0"); } - if (getClass() == BufferedOutputStream.class) { - // use InternalLock and resizable buffer when not sub-classed - this.lock = InternalLock.newLockOrNull(); - this.buf = new byte[initialSize]; // resizable - } else { - // use monitors and no resizing when sub-classed - this.lock = null; - this.buf = new byte[maxSize]; - } + this.buf = new byte[initialSize]; // resizable if initialSize < maxSize this.maxBufSize = maxSize; } @@ -136,8 +124,6 @@ private void flushBuffer() throws IOException { * Grow buf to fit an additional len bytes if needed. * If possible, it grows by len+1 to avoid flushing when len bytes * are added. A no-op if the buffer is not resizable. - * - * This method should only be called while holding the lock. */ private void growIfNeeded(int len) { int neededSize = count + len + 1; @@ -157,22 +143,7 @@ private void growIfNeeded(int len) { * @throws IOException if an I/O error occurs. */ @Override - public void write(int b) throws IOException { - if (lock != null) { - lock.lock(); - try { - implWrite(b); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implWrite(b); - } - } - } - - private void implWrite(int b) throws IOException { + public synchronized void write(int b) throws IOException { growIfNeeded(1); if (count >= buf.length) { flushBuffer(); @@ -198,22 +169,7 @@ private void implWrite(int b) throws IOException { * @throws IndexOutOfBoundsException {@inheritDoc} */ @Override - public void write(byte[] b, int off, int len) throws IOException { - if (lock != null) { - lock.lock(); - try { - implWrite(b, off, len); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implWrite(b, off, len); - } - } - } - - private void implWrite(byte[] b, int off, int len) throws IOException { + public synchronized void write(byte[] b, int off, int len) throws IOException { if (len >= maxBufSize) { /* If the request length exceeds the max size of the output buffer, flush the output buffer and then write the data directly. @@ -238,22 +194,7 @@ private void implWrite(byte[] b, int off, int len) throws IOException { * @see java.io.FilterOutputStream#out */ @Override - public void flush() throws IOException { - if (lock != null) { - lock.lock(); - try { - implFlush(); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implFlush(); - } - } - } - - private void implFlush() throws IOException { + public synchronized void flush() throws IOException { flushBuffer(); out.flush(); } diff --git a/src/java.base/share/classes/java/io/BufferedReader.java b/src/java.base/share/classes/java/io/BufferedReader.java index c2f6b89e08622..a51f0acaf007d 100644 --- a/src/java.base/share/classes/java/io/BufferedReader.java +++ b/src/java.base/share/classes/java/io/BufferedReader.java @@ -32,7 +32,6 @@ import java.util.Spliterators; import java.util.stream.Stream; import java.util.stream.StreamSupport; -import jdk.internal.misc.InternalLock; /** * Reads text from a character-input stream, buffering characters so as to @@ -181,37 +180,23 @@ private void fill() throws IOException { * @throws IOException If an I/O error occurs */ public int read() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return implRead(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - return implRead(); - } - } - } - - private int implRead() throws IOException { - ensureOpen(); - for (;;) { - if (nextChar >= nChars) { - fill(); - if (nextChar >= nChars) - return -1; - } - if (skipLF) { - skipLF = false; - if (cb[nextChar] == '\n') { - nextChar++; - continue; + synchronized (lock) { + ensureOpen(); + for (;;) { + if (nextChar >= nChars) { + fill(); + if (nextChar >= nChars) + return -1; + } + if (skipLF) { + skipLF = false; + if (cb[nextChar] == '\n') { + nextChar++; + continue; + } } + return cb[nextChar++]; } - return cb[nextChar++]; } } @@ -296,36 +281,22 @@ private int read1(char[] cbuf, int off, int len) throws IOException { * @throws IOException {@inheritDoc} */ public int read(char[] cbuf, int off, int len) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return implRead(cbuf, off, len); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - return implRead(cbuf, off, len); + synchronized (lock) { + ensureOpen(); + Objects.checkFromIndexSize(off, len, cbuf.length); + if (len == 0) { + return 0; } - } - } - - private int implRead(char[] cbuf, int off, int len) throws IOException { - ensureOpen(); - Objects.checkFromIndexSize(off, len, cbuf.length); - if (len == 0) { - return 0; - } - int n = read1(cbuf, off, len); - if (n <= 0) return n; - while ((n < len) && in.ready()) { - int n1 = read1(cbuf, off + n, len - n); - if (n1 <= 0) break; - n += n1; + int n = read1(cbuf, off, len); + if (n <= 0) return n; + while ((n < len) && in.ready()) { + int n1 = read1(cbuf, off + n, len - n); + if (n1 <= 0) break; + n += n1; + } + return n; } - return n; } /** @@ -347,81 +318,67 @@ private int implRead(char[] cbuf, int off, int len) throws IOException { * @throws IOException If an I/O error occurs */ String readLine(boolean ignoreLF, boolean[] term) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return implReadLine(ignoreLF, term); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - return implReadLine(ignoreLF, term); - } - } - } + synchronized (lock) { + StringBuilder s = null; + int startChar; - private String implReadLine(boolean ignoreLF, boolean[] term) throws IOException { - StringBuilder s = null; - int startChar; + ensureOpen(); + boolean omitLF = ignoreLF || skipLF; + if (term != null) term[0] = false; - ensureOpen(); - boolean omitLF = ignoreLF || skipLF; - if (term != null) term[0] = false; + bufferLoop: + for (;;) { - bufferLoop: - for (;;) { - - if (nextChar >= nChars) - fill(); - if (nextChar >= nChars) { /* EOF */ - if (s != null && s.length() > 0) - return s.toString(); - else - return null; - } - boolean eol = false; - char c = 0; - int i; + if (nextChar >= nChars) + fill(); + if (nextChar >= nChars) { /* EOF */ + if (s != null && s.length() > 0) + return s.toString(); + else + return null; + } + boolean eol = false; + char c = 0; + int i; - /* Skip a leftover '\n', if necessary */ - if (omitLF && (cb[nextChar] == '\n')) - nextChar++; - skipLF = false; - omitLF = false; - - charLoop: - for (i = nextChar; i < nChars; i++) { - c = cb[i]; - if ((c == '\n') || (c == '\r')) { - if (term != null) term[0] = true; - eol = true; - break charLoop; + /* Skip a leftover '\n', if necessary */ + if (omitLF && (cb[nextChar] == '\n')) + nextChar++; + skipLF = false; + omitLF = false; + + charLoop: + for (i = nextChar; i < nChars; i++) { + c = cb[i]; + if ((c == '\n') || (c == '\r')) { + if (term != null) term[0] = true; + eol = true; + break charLoop; + } } - } - startChar = nextChar; - nextChar = i; + startChar = nextChar; + nextChar = i; - if (eol) { - String str; - if (s == null) { - str = new String(cb, startChar, i - startChar); - } else { - s.append(cb, startChar, i - startChar); - str = s.toString(); - } - nextChar++; - if (c == '\r') { - skipLF = true; + if (eol) { + String str; + if (s == null) { + str = new String(cb, startChar, i - startChar); + } else { + s.append(cb, startChar, i - startChar); + str = s.toString(); + } + nextChar++; + if (c == '\r') { + skipLF = true; + } + return str; } - return str; - } - if (s == null) - s = new StringBuilder(DEFAULT_EXPECTED_LINE_LENGTH); - s.append(cb, startChar, i - startChar); + if (s == null) + s = new StringBuilder(DEFAULT_EXPECTED_LINE_LENGTH); + s.append(cb, startChar, i - startChar); + } } } @@ -450,47 +407,33 @@ public long skip(long n) throws IOException { if (n < 0L) { throw new IllegalArgumentException("skip value is negative"); } - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return implSkip(n); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - return implSkip(n); - } - } - } - - private long implSkip(long n) throws IOException { - ensureOpen(); - long r = n; - while (r > 0) { - if (nextChar >= nChars) - fill(); - if (nextChar >= nChars) /* EOF */ - break; - if (skipLF) { - skipLF = false; - if (cb[nextChar] == '\n') { - nextChar++; + synchronized (lock) { + ensureOpen(); + long r = n; + while (r > 0) { + if (nextChar >= nChars) + fill(); + if (nextChar >= nChars) /* EOF */ + break; + if (skipLF) { + skipLF = false; + if (cb[nextChar] == '\n') { + nextChar++; + } + } + long d = nChars - nextChar; + if (r <= d) { + nextChar += (int)r; + r = 0; + break; + } + else { + r -= d; + nextChar = nChars; } } - long d = nChars - nextChar; - if (r <= d) { - nextChar += (int)r; - r = 0; - break; - } - else { - r -= d; - nextChar = nChars; - } + return n - r; } - return n - r; } /** @@ -501,42 +444,28 @@ private long implSkip(long n) throws IOException { * @throws IOException If an I/O error occurs */ public boolean ready() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return implReady(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - return implReady(); - } - } - } + synchronized (lock) { + ensureOpen(); - private boolean implReady() throws IOException { - ensureOpen(); - - /* - * If newline needs to be skipped and the next char to be read - * is a newline character, then just skip it right away. - */ - if (skipLF) { - /* Note that in.ready() will return true if and only if the next - * read on the stream will not block. + /* + * If newline needs to be skipped and the next char to be read + * is a newline character, then just skip it right away. */ - if (nextChar >= nChars && in.ready()) { - fill(); - } - if (nextChar < nChars) { - if (cb[nextChar] == '\n') - nextChar++; - skipLF = false; + if (skipLF) { + /* Note that in.ready() will return true if and only if the next + * read on the stream will not block. + */ + if (nextChar >= nChars && in.ready()) { + fill(); + } + if (nextChar < nChars) { + if (cb[nextChar] == '\n') + nextChar++; + skipLF = false; + } } + return (nextChar < nChars) || in.ready(); } - return (nextChar < nChars) || in.ready(); } /** @@ -566,28 +495,14 @@ public void mark(int readAheadLimit) throws IOException { if (readAheadLimit < 0) { throw new IllegalArgumentException("Read-ahead limit < 0"); } - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implMark(readAheadLimit); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implMark(readAheadLimit); - } + synchronized (lock) { + ensureOpen(); + this.readAheadLimit = readAheadLimit; + markedChar = nextChar; + markedSkipLF = skipLF; } } - private void implMark(int readAheadLimit) throws IOException { - ensureOpen(); - this.readAheadLimit = readAheadLimit; - markedChar = nextChar; - markedSkipLF = skipLF; - } - /** * Resets the stream to the most recent mark. * @@ -595,55 +510,27 @@ private void implMark(int readAheadLimit) throws IOException { * or if the mark has been invalidated */ public void reset() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implReset(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implReset(); - } + synchronized (lock) { + ensureOpen(); + if (markedChar < 0) + throw new IOException((markedChar == INVALIDATED) + ? "Mark invalid" + : "Stream not marked"); + nextChar = markedChar; + skipLF = markedSkipLF; } } - private void implReset() throws IOException { - ensureOpen(); - if (markedChar < 0) - throw new IOException((markedChar == INVALIDATED) - ? "Mark invalid" - : "Stream not marked"); - nextChar = markedChar; - skipLF = markedSkipLF; - } - public void close() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { + if (in == null) + return; try { - implClose(); + in.close(); } finally { - locker.unlock(); + in = null; + cb = null; } - } else { - synchronized (lock) { - implClose(); - } - } - } - - private void implClose() throws IOException { - if (in == null) - return; - try { - in.close(); - } finally { - in = null; - cb = null; } } diff --git a/src/java.base/share/classes/java/io/BufferedWriter.java b/src/java.base/share/classes/java/io/BufferedWriter.java index 17862a265ae82..e3f8a21fe60bb 100644 --- a/src/java.base/share/classes/java/io/BufferedWriter.java +++ b/src/java.base/share/classes/java/io/BufferedWriter.java @@ -27,7 +27,6 @@ import java.util.Arrays; import java.util.Objects; -import jdk.internal.misc.InternalLock; import jdk.internal.misc.VM; /** @@ -162,58 +161,30 @@ private void growIfNeeded(int len) { * may be invoked by PrintStream. */ void flushBuffer() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implFlushBuffer(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implFlushBuffer(); - } + synchronized (lock) { + ensureOpen(); + if (nextChar == 0) + return; + out.write(cb, 0, nextChar); + nextChar = 0; } } - private void implFlushBuffer() throws IOException { - ensureOpen(); - if (nextChar == 0) - return; - out.write(cb, 0, nextChar); - nextChar = 0; - } - /** * Writes a single character. * * @throws IOException If an I/O error occurs */ public void write(int c) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implWrite(c); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implWrite(c); - } + synchronized (lock) { + ensureOpen(); + growIfNeeded(1); + if (nextChar >= nChars) + flushBuffer(); + cb[nextChar++] = (char) c; } } - private void implWrite(int c) throws IOException { - ensureOpen(); - growIfNeeded(1); - if (nextChar >= nChars) - flushBuffer(); - cb[nextChar++] = (char) c; - } - /** * Our own little min method, to avoid loading java.lang.Math if we've run * out of file descriptors and we're trying to print a stack trace. @@ -245,46 +216,32 @@ private int min(int a, int b) { * @throws IOException If an I/O error occurs */ public void write(char[] cbuf, int off, int len) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implWrite(cbuf, off, len); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implWrite(cbuf, off, len); + synchronized (lock) { + ensureOpen(); + Objects.checkFromIndexSize(off, len, cbuf.length); + if (len == 0) { + return; } - } - } - private void implWrite(char[] cbuf, int off, int len) throws IOException { - ensureOpen(); - Objects.checkFromIndexSize(off, len, cbuf.length); - if (len == 0) { - return; - } - - if (len >= maxChars) { - /* If the request length exceeds the max size of the output buffer, - flush the buffer and then write the data directly. In this - way buffered streams will cascade harmlessly. */ - flushBuffer(); - out.write(cbuf, off, len); - return; - } - - growIfNeeded(len); - int b = off, t = off + len; - while (b < t) { - int d = min(nChars - nextChar, t - b); - System.arraycopy(cbuf, b, cb, nextChar, d); - b += d; - nextChar += d; - if (nextChar >= nChars) { + if (len >= maxChars) { + /* If the request length exceeds the max size of the output buffer, + flush the buffer and then write the data directly. In this + way buffered streams will cascade harmlessly. */ flushBuffer(); + out.write(cbuf, off, len); + return; + } + + growIfNeeded(len); + int b = off, t = off + len; + while (b < t) { + int d = min(nChars - nextChar, t - b); + System.arraycopy(cbuf, b, cb, nextChar, d); + b += d; + nextChar += d; + if (nextChar >= nChars) { + flushBuffer(); + } } } } @@ -312,35 +269,21 @@ private void implWrite(char[] cbuf, int off, int len) throws IOException { * @throws IOException If an I/O error occurs */ public void write(String s, int off, int len) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implWrite(s, off, len); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implWrite(s, off, len); + synchronized (lock) { + ensureOpen(); + growIfNeeded(len); + int b = off, t = off + len; + while (b < t) { + int d = min(nChars - nextChar, t - b); + s.getChars(b, b + d, cb, nextChar); + b += d; + nextChar += d; + if (nextChar >= nChars) + flushBuffer(); } } } - private void implWrite(String s, int off, int len) throws IOException { - ensureOpen(); - growIfNeeded(len); - int b = off, t = off + len; - while (b < t) { - int d = min(nChars - nextChar, t - b); - s.getChars(b, b + d, cb, nextChar); - b += d; - nextChar += d; - if (nextChar >= nChars) - flushBuffer(); - } - } - /** * Writes a line separator. The line separator string is defined by the * system property {@code line.separator}, and is not necessarily a single @@ -358,52 +301,24 @@ public void newLine() throws IOException { * @throws IOException If an I/O error occurs */ public void flush() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implFlush(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implFlush(); - } + synchronized (lock) { + flushBuffer(); + out.flush(); } } - private void implFlush() throws IOException { - flushBuffer(); - out.flush(); - } - + @SuppressWarnings("try") public void close() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implClose(); - } finally { - locker.unlock(); + synchronized (lock) { + if (out == null) { + return; } - } else { - synchronized (lock) { - implClose(); + try (Writer w = out) { + flushBuffer(); + } finally { + out = null; + cb = null; } } } - - @SuppressWarnings("try") - private void implClose() throws IOException { - if (out == null) { - return; - } - try (Writer w = out) { - flushBuffer(); - } finally { - out = null; - cb = null; - } - } } diff --git a/src/java.base/share/classes/java/io/InputStreamReader.java b/src/java.base/share/classes/java/io/InputStreamReader.java index d3033b15b9f72..6d43c4ae0cdc6 100644 --- a/src/java.base/share/classes/java/io/InputStreamReader.java +++ b/src/java.base/share/classes/java/io/InputStreamReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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 @@ -28,7 +28,6 @@ import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; -import jdk.internal.misc.InternalLock; import sun.nio.cs.StreamDecoder; /** @@ -62,20 +61,6 @@ public class InputStreamReader extends Reader { private final StreamDecoder sd; - /** - * Return the lock object for the given reader's stream decoder. - * If the reader type is trusted then an internal lock can be used. If the - * reader type is not trusted then the reader object is the lock. - */ - private static Object lockFor(InputStreamReader reader) { - Class clazz = reader.getClass(); - if (clazz == InputStreamReader.class || clazz == FileReader.class) { - return InternalLock.newLockOr(reader); - } else { - return reader; - } - } - /** * Creates an InputStreamReader that uses the * {@link Charset#defaultCharset() default charset}. @@ -88,7 +73,7 @@ private static Object lockFor(InputStreamReader reader) { public InputStreamReader(InputStream in) { super(in); Charset cs = Charset.defaultCharset(); - sd = StreamDecoder.forInputStreamReader(in, lockFor(this), cs); + sd = StreamDecoder.forInputStreamReader(in, this, cs); } /** @@ -110,7 +95,7 @@ public InputStreamReader(InputStream in, String charsetName) super(in); if (charsetName == null) throw new NullPointerException("charsetName"); - sd = StreamDecoder.forInputStreamReader(in, lockFor(this), charsetName); + sd = StreamDecoder.forInputStreamReader(in, this, charsetName); } /** @@ -126,7 +111,7 @@ public InputStreamReader(InputStream in, Charset cs) { super(in); if (cs == null) throw new NullPointerException("charset"); - sd = StreamDecoder.forInputStreamReader(in, lockFor(this), cs); + sd = StreamDecoder.forInputStreamReader(in, this, cs); } /** @@ -142,7 +127,7 @@ public InputStreamReader(InputStream in, CharsetDecoder dec) { super(in); if (dec == null) throw new NullPointerException("charset decoder"); - sd = StreamDecoder.forInputStreamReader(in, lockFor(this), dec); + sd = StreamDecoder.forInputStreamReader(in, this, dec); } /** diff --git a/src/java.base/share/classes/java/io/OutputStreamWriter.java b/src/java.base/share/classes/java/io/OutputStreamWriter.java index cda9fead18e64..9a16aa140bc47 100644 --- a/src/java.base/share/classes/java/io/OutputStreamWriter.java +++ b/src/java.base/share/classes/java/io/OutputStreamWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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 @@ -28,7 +28,6 @@ import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; -import jdk.internal.misc.InternalLock; import sun.nio.cs.StreamEncoder; /** @@ -75,20 +74,6 @@ public class OutputStreamWriter extends Writer { private final StreamEncoder se; - /** - * Return the lock object for the given writer's stream encoder. - * If the writer type is trusted then an internal lock can be used. If the - * writer type is not trusted then the writer object is the lock. - */ - private static Object lockFor(OutputStreamWriter writer) { - Class clazz = writer.getClass(); - if (clazz == OutputStreamWriter.class || clazz == FileWriter.class) { - return InternalLock.newLockOr(writer); - } else { - return writer; - } - } - /** * Creates an OutputStreamWriter that uses the named charset. * @@ -108,7 +93,7 @@ public OutputStreamWriter(OutputStream out, String charsetName) super(out); if (charsetName == null) throw new NullPointerException("charsetName"); - se = StreamEncoder.forOutputStreamWriter(out, lockFor(this), charsetName); + se = StreamEncoder.forOutputStreamWriter(out, this, charsetName); } /** @@ -122,7 +107,7 @@ public OutputStreamWriter(OutputStream out, String charsetName) @SuppressWarnings("this-escape") public OutputStreamWriter(OutputStream out) { super(out); - se = StreamEncoder.forOutputStreamWriter(out, lockFor(this), + se = StreamEncoder.forOutputStreamWriter(out, this, out instanceof PrintStream ps ? ps.charset() : Charset.defaultCharset()); } @@ -142,7 +127,7 @@ public OutputStreamWriter(OutputStream out, Charset cs) { super(out); if (cs == null) throw new NullPointerException("charset"); - se = StreamEncoder.forOutputStreamWriter(out, lockFor(this), cs); + se = StreamEncoder.forOutputStreamWriter(out, this, cs); } /** @@ -161,7 +146,7 @@ public OutputStreamWriter(OutputStream out, CharsetEncoder enc) { super(out); if (enc == null) throw new NullPointerException("charset encoder"); - se = StreamEncoder.forOutputStreamWriter(out, lockFor(this), enc); + se = StreamEncoder.forOutputStreamWriter(out, this, enc); } /** diff --git a/src/java.base/share/classes/java/io/PrintStream.java b/src/java.base/share/classes/java/io/PrintStream.java index 35e2716dbd324..11b71b5d2ae11 100644 --- a/src/java.base/share/classes/java/io/PrintStream.java +++ b/src/java.base/share/classes/java/io/PrintStream.java @@ -32,7 +32,6 @@ import java.nio.charset.UnsupportedCharsetException; import jdk.internal.access.JavaIOPrintStreamAccess; import jdk.internal.access.SharedSecrets; -import jdk.internal.misc.InternalLock; /** * A {@code PrintStream} adds functionality to another output stream, @@ -67,9 +66,6 @@ public class PrintStream extends FilterOutputStream implements Appendable, Closeable { - // initialized to null when PrintStream is sub-classed - private final InternalLock lock; - private final boolean autoFlush; private boolean trouble = false; private Formatter formatter; @@ -117,13 +113,6 @@ private PrintStream(boolean autoFlush, OutputStream out) { this.charset = out instanceof PrintStream ps ? ps.charset() : Charset.defaultCharset(); this.charOut = new OutputStreamWriter(this, charset); this.textOut = new BufferedWriter(charOut); - - // use monitors when PrintStream is sub-classed - if (getClass() == PrintStream.class) { - lock = InternalLock.newLockOrNull(); - } else { - lock = null; - } } /* Variant of the private constructor so that the given charset name @@ -220,13 +209,6 @@ public PrintStream(OutputStream out, boolean autoFlush, Charset charset) { this.charOut = new OutputStreamWriter(this, charset); this.textOut = new BufferedWriter(charOut); this.charset = charset; - - // use monitors when PrintStream is sub-classed - if (getClass() == PrintStream.class) { - lock = InternalLock.newLockOrNull(); - } else { - lock = null; - } } /** @@ -448,30 +430,17 @@ private void ensureOpen() throws IOException { */ @Override public void flush() { - if (lock != null) { - lock.lock(); + synchronized (this) { try { - implFlush(); - } finally { - lock.unlock(); + ensureOpen(); + out.flush(); } - } else { - synchronized (this) { - implFlush(); + catch (IOException x) { + trouble = true; } } } - private void implFlush() { - try { - ensureOpen(); - out.flush(); - } - catch (IOException x) { - trouble = true; - } - } - private boolean closing = false; /* To avoid recursive closing */ /** @@ -482,33 +451,20 @@ private void implFlush() { */ @Override public void close() { - if (lock != null) { - lock.lock(); - try { - implClose(); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implClose(); - } - } - } - - private void implClose() { - if (!closing) { - closing = true; - try { - textOut.close(); - out.close(); - } - catch (IOException x) { - trouble = true; + synchronized (this) { + if (!closing) { + closing = true; + try { + textOut.close(); + out.close(); + } + catch (IOException x) { + trouble = true; + } + textOut = null; + charOut = null; + out = null; } - textOut = null; - charOut = null; - out = null; } } @@ -575,17 +531,11 @@ protected void clearError() { @Override public void write(int b) { try { - if (lock != null) { - lock.lock(); - try { - implWrite(b); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implWrite(b); - } + synchronized (this) { + ensureOpen(); + out.write(b); + if ((b == '\n') && autoFlush) + out.flush(); } } catch (InterruptedIOException x) { @@ -596,13 +546,6 @@ public void write(int b) { } } - private void implWrite(int b) throws IOException { - ensureOpen(); - out.write(b); - if ((b == '\n') && autoFlush) - out.flush(); - } - /** * Writes {@code len} bytes from the specified byte array starting at * offset {@code off} to this stream. If automatic flushing is @@ -621,17 +564,11 @@ private void implWrite(int b) throws IOException { @Override public void write(byte[] buf, int off, int len) { try { - if (lock != null) { - lock.lock(); - try { - implWrite(buf, off, len); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implWrite(buf, off, len); - } + synchronized (this) { + ensureOpen(); + out.write(buf, off, len); + if (autoFlush) + out.flush(); } } catch (InterruptedIOException x) { @@ -642,14 +579,6 @@ public void write(byte[] buf, int off, int len) { } } - private void implWrite(byte[] buf, int off, int len) throws IOException { - ensureOpen(); - out.write(buf, off, len); - if (autoFlush) - out.flush(); - } - - /** * Writes all bytes from the specified byte array to this stream. If * automatic flushing is enabled then the {@code flush} method will be @@ -714,16 +643,17 @@ public void writeBytes(byte[] buf) { private void write(char[] buf) { try { - if (lock != null) { - lock.lock(); - try { - implWrite(buf); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implWrite(buf); + synchronized (this) { + ensureOpen(); + textOut.write(buf); + textOut.flushBuffer(); + charOut.flushBuffer(); + if (autoFlush) { + for (int i = 0; i < buf.length; i++) + if (buf[i] == '\n') { + out.flush(); + break; + } } } } catch (InterruptedIOException x) { @@ -733,37 +663,20 @@ private void write(char[] buf) { } } - private void implWrite(char[] buf) throws IOException { - ensureOpen(); - textOut.write(buf); - textOut.flushBuffer(); - charOut.flushBuffer(); - if (autoFlush) { - for (int i = 0; i < buf.length; i++) - if (buf[i] == '\n') { - out.flush(); - break; - } - } - } - // Used to optimize away back-to-back flushing and synchronization when // using println, but since subclasses could exist which depend on // observing a call to print followed by newLine() we only use this if // getClass() == PrintStream.class to avoid compatibility issues. private void writeln(char[] buf) { try { - if (lock != null) { - lock.lock(); - try { - implWriteln(buf); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implWriteln(buf); - } + synchronized (this) { + ensureOpen(); + textOut.write(buf); + textOut.newLine(); + textOut.flushBuffer(); + charOut.flushBuffer(); + if (autoFlush) + out.flush(); } } catch (InterruptedIOException x) { @@ -774,29 +687,15 @@ private void writeln(char[] buf) { } } - private void implWriteln(char[] buf) throws IOException { - ensureOpen(); - textOut.write(buf); - textOut.newLine(); - textOut.flushBuffer(); - charOut.flushBuffer(); - if (autoFlush) - out.flush(); - } - private void write(String s) { try { - if (lock != null) { - lock.lock(); - try { - implWrite(s); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implWrite(s); - } + synchronized (this) { + ensureOpen(); + textOut.write(s); + textOut.flushBuffer(); + charOut.flushBuffer(); + if (autoFlush && (s.indexOf('\n') >= 0)) + out.flush(); } } catch (InterruptedIOException x) { @@ -807,32 +706,20 @@ private void write(String s) { } } - private void implWrite(String s) throws IOException { - ensureOpen(); - textOut.write(s); - textOut.flushBuffer(); - charOut.flushBuffer(); - if (autoFlush && (s.indexOf('\n') >= 0)) - out.flush(); - } - // Used to optimize away back-to-back flushing and synchronization when // using println, but since subclasses could exist which depend on // observing a call to print followed by newLine we only use this if // getClass() == PrintStream.class to avoid compatibility issues. private void writeln(String s) { try { - if (lock != null) { - lock.lock(); - try { - implWriteln(s); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implWriteln(s); - } + synchronized (this) { + ensureOpen(); + textOut.write(s); + textOut.newLine(); + textOut.flushBuffer(); + charOut.flushBuffer(); + if (autoFlush) + out.flush(); } } catch (InterruptedIOException x) { @@ -843,29 +730,15 @@ private void writeln(String s) { } } - private void implWriteln(String s) throws IOException { - ensureOpen(); - textOut.write(s); - textOut.newLine(); - textOut.flushBuffer(); - charOut.flushBuffer(); - if (autoFlush) - out.flush(); - } - private void newLine() { try { - if (lock != null) { - lock.lock(); - try { - implNewLine(); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implNewLine(); - } + synchronized (this) { + ensureOpen(); + textOut.newLine(); + textOut.flushBuffer(); + charOut.flushBuffer(); + if (autoFlush) + out.flush(); } } catch (InterruptedIOException x) { @@ -876,15 +749,6 @@ private void newLine() { } } - private void implNewLine() throws IOException { - ensureOpen(); - textOut.newLine(); - textOut.flushBuffer(); - charOut.flushBuffer(); - if (autoFlush) - out.flush(); - } - /* Methods that do not terminate lines */ /** @@ -1342,17 +1206,11 @@ public PrintStream printf(Locale l, String format, Object ... args) { */ public PrintStream format(String format, Object ... args) { try { - if (lock != null) { - lock.lock(); - try { - implFormat(format, args); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implFormat(format, args); - } + synchronized (this) { + ensureOpen(); + if ((formatter == null) || (formatter.locale() != Locale.getDefault(Locale.Category.FORMAT))) + formatter = new Formatter((Appendable) this); + formatter.format(Locale.getDefault(Locale.Category.FORMAT), format, args); } } catch (InterruptedIOException x) { Thread.currentThread().interrupt(); @@ -1362,13 +1220,6 @@ public PrintStream format(String format, Object ... args) { return this; } - private void implFormat(String format, Object ... args) throws IOException { - ensureOpen(); - if ((formatter == null) || (formatter.locale() != Locale.getDefault(Locale.Category.FORMAT))) - formatter = new Formatter((Appendable) this); - formatter.format(Locale.getDefault(Locale.Category.FORMAT), format, args); - } - /** * Writes a formatted string to this output stream using the specified * format string and arguments. @@ -1411,17 +1262,11 @@ private void implFormat(String format, Object ... args) throws IOException { */ public PrintStream format(Locale l, String format, Object ... args) { try { - if (lock != null) { - lock.lock(); - try { - implFormat(l, format, args); - } finally { - lock.unlock(); - } - } else { - synchronized (this) { - implFormat(l, format, args); - } + synchronized (this) { + ensureOpen(); + if ((formatter == null) || (formatter.locale() != l)) + formatter = new Formatter(this, l); + formatter.format(l, format, args); } } catch (InterruptedIOException x) { Thread.currentThread().interrupt(); @@ -1431,13 +1276,6 @@ public PrintStream format(Locale l, String format, Object ... args) { return this; } - private void implFormat(Locale l, String format, Object ... args) throws IOException { - ensureOpen(); - if ((formatter == null) || (formatter.locale() != l)) - formatter = new Formatter(this, l); - formatter.format(l, format, args); - } - /** * Appends the specified character sequence to this output stream. * @@ -1543,8 +1381,7 @@ public Charset charset() { static { SharedSecrets.setJavaIOCPrintStreamAccess(new JavaIOPrintStreamAccess() { public Object lock(PrintStream ps) { - Object lock = ps.lock; - return (lock != null) ? lock : ps; + return ps; } }); } diff --git a/src/java.base/share/classes/java/io/PrintWriter.java b/src/java.base/share/classes/java/io/PrintWriter.java index 2ed9315ba6a30..07c1514f26143 100644 --- a/src/java.base/share/classes/java/io/PrintWriter.java +++ b/src/java.base/share/classes/java/io/PrintWriter.java @@ -33,7 +33,6 @@ 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 @@ -405,30 +404,16 @@ private void ensureOpen() throws IOException { * @see #checkError() */ public void flush() { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { try { - implFlush(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implFlush(); + ensureOpen(); + out.flush(); + } catch (IOException x) { + trouble = true; } } } - private void implFlush() { - try { - ensureOpen(); - out.flush(); - } catch (IOException x) { - trouble = true; - } - } - /** * Closes the stream and releases any system resources associated * with it. Closing a previously closed stream has no effect. @@ -437,28 +422,15 @@ private void implFlush() { */ public void close() { Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { try { - implClose(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implClose(); - } - } - } - - private void implClose() { - try { - if (out != null) { - out.close(); - out = null; + if (out != null) { + out.close(); + out = null; + } + } catch (IOException x) { + trouble = true; } - } catch (IOException x) { - trouble = true; } } @@ -515,32 +487,18 @@ protected void clearError() { * @param c int specifying a character to be written. */ public void write(int c) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { try { - implWrite(c); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implWrite(c); + ensureOpen(); + out.write(c); + } catch (InterruptedIOException x) { + Thread.currentThread().interrupt(); + } catch (IOException x) { + trouble = true; } } } - private void implWrite(int c) { - try { - ensureOpen(); - out.write(c); - } catch (InterruptedIOException x) { - Thread.currentThread().interrupt(); - } catch (IOException x) { - trouble = true; - } - } - /** * Writes A Portion of an array of characters. * @param buf Array of characters @@ -553,29 +511,15 @@ private void implWrite(int c) { * to throw an {@code IndexOutOfBoundsException} */ public void write(char[] buf, int off, int len) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { try { - implWrite(buf, off, len); - } finally { - locker.unlock(); + ensureOpen(); + out.write(buf, off, len); + } catch (InterruptedIOException x) { + Thread.currentThread().interrupt(); + } catch (IOException x) { + trouble = true; } - } else { - synchronized (lock) { - implWrite(buf, off, len); - } - } - } - - private void implWrite(char[] buf, int off, int len) { - try { - ensureOpen(); - out.write(buf, off, len); - } catch (InterruptedIOException x) { - Thread.currentThread().interrupt(); - } catch (IOException x) { - trouble = true; } } @@ -600,32 +544,18 @@ public void write(char[] buf) { * to throw an {@code IndexOutOfBoundsException} */ public void write(String s, int off, int len) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { try { - implWrite(s, off, len); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implWrite(s, off, len); + ensureOpen(); + out.write(s, off, len); + } catch (InterruptedIOException x) { + Thread.currentThread().interrupt(); + } catch (IOException x) { + trouble = true; } } } - private void implWrite(String s, int off, int len) { - try { - ensureOpen(); - out.write(s, off, len); - } catch (InterruptedIOException x) { - Thread.currentThread().interrupt(); - } catch (IOException x) { - trouble = true; - } - } - /** * Writes a string. This method cannot be inherited from the Writer class * because it must suppress I/O exceptions. @@ -636,34 +566,20 @@ public void write(String s) { } private void newLine() { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { try { - implNewLine(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implNewLine(); + ensureOpen(); + out.write(System.lineSeparator()); + if (autoFlush) + out.flush(); + } catch (InterruptedIOException x) { + Thread.currentThread().interrupt(); + } catch (IOException x) { + trouble = true; } } } - private void implNewLine() { - try { - ensureOpen(); - out.write(System.lineSeparator()); - if (autoFlush) - out.flush(); - } catch (InterruptedIOException x) { - Thread.currentThread().interrupt(); - } catch (IOException x) { - trouble = true; - } - } - /* Methods that do not terminate lines */ /** @@ -816,20 +732,9 @@ public void println() { * @param x the {@code boolean} value to be printed */ public void println(boolean x) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(x); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(x); - println(); - } + synchronized (lock) { + print(x); + println(); } } @@ -841,20 +746,9 @@ public void println(boolean x) { * @param x the {@code char} value to be printed */ public void println(char x) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(x); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(x); - println(); - } + synchronized (lock) { + print(x); + println(); } } @@ -866,20 +760,9 @@ public void println(char x) { * @param x the {@code int} value to be printed */ public void println(int x) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(x); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(x); - println(); - } + synchronized (lock) { + print(x); + println(); } } @@ -891,20 +774,9 @@ public void println(int x) { * @param x the {@code long} value to be printed */ public void println(long x) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(x); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(x); - println(); - } + synchronized (lock) { + print(x); + println(); } } @@ -916,20 +788,9 @@ public void println(long x) { * @param x the {@code float} value to be printed */ public void println(float x) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(x); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(x); - println(); - } + synchronized (lock) { + print(x); + println(); } } @@ -941,20 +802,9 @@ public void println(float x) { * @param x the {@code double} value to be printed */ public void println(double x) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(x); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(x); - println(); - } + synchronized (lock) { + print(x); + println(); } } @@ -966,20 +816,9 @@ public void println(double x) { * @param x the array of {@code char} values to be printed */ public void println(char[] x) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(x); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(x); - println(); - } + synchronized (lock) { + print(x); + println(); } } @@ -991,20 +830,9 @@ public void println(char[] x) { * @param x the {@code String} value to be printed */ public void println(String x) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(x); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(x); - println(); - } + synchronized (lock) { + print(x); + println(); } } @@ -1019,20 +847,9 @@ public void println(String x) { */ public void println(Object x) { String s = String.valueOf(x); - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - print(s); - println(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - print(s); - println(); - } + synchronized (lock) { + print(s); + println(); } } @@ -1178,38 +995,24 @@ public PrintWriter printf(Locale l, String format, Object ... args) { * @since 1.5 */ public PrintWriter format(String format, Object ... args) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { try { - implFormat(format, args); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implFormat(format, args); + 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; } - private void implFormat(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; - } - } - /** * Writes a formatted string to this writer using the specified format * string and arguments. If automatic flushing is enabled, calls to this @@ -1252,37 +1055,23 @@ private void implFormat(String format, Object ... args) { * @since 1.5 */ public PrintWriter format(Locale l, String format, Object ... args) { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { try { - implFormat(l, format, args); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implFormat(l, format, args); + 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; } - private void implFormat(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; - } - } - /** * Appends the specified character sequence to this writer. * diff --git a/src/java.base/share/classes/java/io/PushbackInputStream.java b/src/java.base/share/classes/java/io/PushbackInputStream.java index 0c74205ba0e11..5aa0e133df97e 100644 --- a/src/java.base/share/classes/java/io/PushbackInputStream.java +++ b/src/java.base/share/classes/java/io/PushbackInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2024, 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 @@ -27,7 +27,6 @@ import java.util.Arrays; import java.util.Objects; -import jdk.internal.misc.InternalLock; /** * A {@code PushbackInputStream} adds @@ -54,10 +53,6 @@ * @since 1.0 */ public class PushbackInputStream extends FilterInputStream { - - // initialized to null when PushbackInputStream is sub-classed - private final InternalLock closeLock; - /** * The pushback buffer. * @since 1.1 @@ -101,13 +96,6 @@ public PushbackInputStream(InputStream in, int size) { } this.buf = new byte[size]; this.pos = size; - - // use monitors when PushbackInputStream is sub-classed - if (getClass() == PushbackInputStream.class) { - closeLock = InternalLock.newLockOrNull(); - } else { - closeLock = null; - } } /** @@ -386,27 +374,12 @@ public void reset() throws IOException { * * @throws IOException if an I/O error occurs. */ - public void close() throws IOException { - if (closeLock != null) { - closeLock.lock(); - try { - implClose(); - } finally { - closeLock.unlock(); - } - } else { - synchronized (this) { - implClose(); - } - } - } - - private void implClose() throws IOException { - if (in != null) { - in.close(); - in = null; - buf = null; - } + public synchronized void close() throws IOException { + if (in == null) + return; + in.close(); + in = null; + buf = null; } @Override diff --git a/src/java.base/share/classes/java/io/Reader.java b/src/java.base/share/classes/java/io/Reader.java index 9fca28a3a96cf..1654156bee19a 100644 --- a/src/java.base/share/classes/java/io/Reader.java +++ b/src/java.base/share/classes/java/io/Reader.java @@ -28,7 +28,6 @@ import java.nio.CharBuffer; import java.nio.ReadOnlyBufferException; import java.util.Objects; -import jdk.internal.misc.InternalLock; /** * Abstract class for reading character streams. The only methods that a @@ -283,21 +282,6 @@ protected Reader(Object lock) { this.lock = lock; } - /** - * For use by BufferedReader to create a character-stream reader that uses an - * internal lock when BufferedReader is not extended and the given reader is - * trusted, otherwise critical sections will synchronize on the given reader. - */ - Reader(Reader in) { - Class clazz = in.getClass(); - if (getClass() == BufferedReader.class && - (clazz == InputStreamReader.class || clazz == FileReader.class)) { - this.lock = InternalLock.newLockOr(in); - } else { - this.lock = in; - } - } - /** * Attempts to read characters into the specified character buffer. * The buffer is used as a repository of characters as-is: the only @@ -429,33 +413,19 @@ public int read(char[] cbuf) throws IOException { public long skip(long n) throws IOException { if (n < 0L) throw new IllegalArgumentException("skip value is negative"); - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return implSkip(n); - } finally { - locker.unlock(); + synchronized (lock) { + int nn = (int) Math.min(n, maxSkipBufferSize); + if ((skipBuffer == null) || (skipBuffer.length < nn)) + skipBuffer = new char[nn]; + long r = n; + while (r > 0) { + int nc = read(skipBuffer, 0, (int)Math.min(r, nn)); + if (nc == -1) + break; + r -= nc; } - } else { - synchronized (lock) { - return implSkip(n); - } - } - } - - private long implSkip(long n) throws IOException { - int nn = (int) Math.min(n, maxSkipBufferSize); - if ((skipBuffer == null) || (skipBuffer.length < nn)) - skipBuffer = new char[nn]; - long r = n; - while (r > 0) { - int nc = read(skipBuffer, 0, (int)Math.min(r, nn)); - if (nc == -1) - break; - r -= nc; + return n - r; } - return n - r; } /** diff --git a/src/java.base/share/classes/java/io/Writer.java b/src/java.base/share/classes/java/io/Writer.java index 62fe6b053e5ef..433a116a4bbcd 100644 --- a/src/java.base/share/classes/java/io/Writer.java +++ b/src/java.base/share/classes/java/io/Writer.java @@ -26,7 +26,6 @@ package java.io; import java.util.Objects; -import jdk.internal.misc.InternalLock; /** * Abstract class for writing to character streams. The only methods that a @@ -162,21 +161,6 @@ protected Writer() { this.lock = this; } - /** - * For use by BufferedWriter to create a character-stream writer that uses an - * internal lock when BufferedWriter is not extended and the given writer is - * trusted, otherwise critical sections will synchronize on the given writer. - */ - Writer(Writer writer) { - Class clazz = writer.getClass(); - if (getClass() == BufferedWriter.class && - (clazz == OutputStreamWriter.class || clazz == FileWriter.class)) { - this.lock = InternalLock.newLockOr(writer); - } else { - this.lock = writer; - } - } - /** * Creates a new character-stream writer whose critical sections will * synchronize on the given object. @@ -206,29 +190,15 @@ protected Writer(Object lock) { * If an I/O error occurs */ public void write(int c) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implWrite(c); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implWrite(c); + synchronized (lock) { + if (writeBuffer == null){ + writeBuffer = new char[WRITE_BUFFER_SIZE]; } + writeBuffer[0] = (char) c; + write(writeBuffer, 0, 1); } } - private void implWrite(int c) throws IOException { - if (writeBuffer == null){ - writeBuffer = new char[WRITE_BUFFER_SIZE]; - } - writeBuffer[0] = (char) c; - write(writeBuffer, 0, 1); - } - /** * Writes an array of characters. * @@ -305,33 +275,19 @@ public void write(String str) throws IOException { * If an I/O error occurs */ public void write(String str, int off, int len) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - implWrite(str, off, len); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - implWrite(str, off, len); - } - } - } - - private void implWrite(String str, int off, int len) throws IOException { - char cbuf[]; - if (len <= WRITE_BUFFER_SIZE) { - if (writeBuffer == null) { - writeBuffer = new char[WRITE_BUFFER_SIZE]; + synchronized (lock) { + char cbuf[]; + if (len <= WRITE_BUFFER_SIZE) { + if (writeBuffer == null) { + writeBuffer = new char[WRITE_BUFFER_SIZE]; + } + cbuf = writeBuffer; + } else { // Don't permanently allocate very large buffers. + cbuf = new char[len]; } - cbuf = writeBuffer; - } else { // Don't permanently allocate very large buffers. - cbuf = new char[len]; + str.getChars(off, (off + len), cbuf, 0); + write(cbuf, 0, len); } - str.getChars(off, (off + len), cbuf, 0); - write(cbuf, 0, len); } /** From 21c9c5e246d82b8aa931d4df44d039089d6f86f5 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 13 Nov 2024 10:32:30 -0800 Subject: [PATCH 2/8] 8343039: Remove use of InternalLock from Stream{De,En}coder and throwable; remove InternalLock class; address comments on BIS and BOS --- .../classes/java/io/BufferedInputStream.java | 6 +- .../classes/java/io/BufferedOutputStream.java | 5 + .../share/classes/java/lang/Throwable.java | 54 ++--- .../jdk/internal/misc/InternalLock.java | 84 ------- .../classes/sun/nio/cs/StreamDecoder.java | 211 ++++++------------ .../classes/sun/nio/cs/StreamEncoder.java | 121 +++------- 6 files changed, 121 insertions(+), 360 deletions(-) delete mode 100644 src/java.base/share/classes/jdk/internal/misc/InternalLock.java diff --git a/src/java.base/share/classes/java/io/BufferedInputStream.java b/src/java.base/share/classes/java/io/BufferedInputStream.java index d3b706f468562..3661be8236c57 100644 --- a/src/java.base/share/classes/java/io/BufferedInputStream.java +++ b/src/java.base/share/classes/java/io/BufferedInputStream.java @@ -238,7 +238,11 @@ public BufferedInputStream(InputStream in, int size) { throw new IllegalArgumentException("Buffer size <= 0"); } initialSize = size; - buf = new byte[size]; + if (getClass() == BufferedInputStream.class) { + buf = EMPTY; + } else { + buf = new byte[size]; + } } /** diff --git a/src/java.base/share/classes/java/io/BufferedOutputStream.java b/src/java.base/share/classes/java/io/BufferedOutputStream.java index be01baf64462c..460689bd6b8c6 100644 --- a/src/java.base/share/classes/java/io/BufferedOutputStream.java +++ b/src/java.base/share/classes/java/io/BufferedOutputStream.java @@ -86,6 +86,11 @@ private BufferedOutputStream(OutputStream out, int initialSize, int maxSize) { } this.buf = new byte[initialSize]; // resizable if initialSize < maxSize + if (getClass() == BufferedOutputStream.class) { + this.buf = new byte[initialSize]; // resizable + } else { + this.buf = new byte[maxSize]; + } this.maxBufSize = maxSize; } diff --git a/src/java.base/share/classes/java/lang/Throwable.java b/src/java.base/share/classes/java/lang/Throwable.java index 275961a9a9f18..ca2c4071b3df5 100644 --- a/src/java.base/share/classes/java/lang/Throwable.java +++ b/src/java.base/share/classes/java/lang/Throwable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2024, 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 @@ -29,7 +29,6 @@ import java.util.*; import jdk.internal.access.SharedSecrets; import jdk.internal.event.ThrowableTracer; -import jdk.internal.misc.InternalLock; /** * The {@code Throwable} class is the superclass of all errors and @@ -689,39 +688,27 @@ public void printStackTrace(PrintStream s) { } private void printStackTrace(PrintStreamOrWriter s) { - Object lock = s.lock(); - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - lockedPrintStackTrace(s); - } finally { - locker.unlock(); - } - } else synchronized (lock) { - lockedPrintStackTrace(s); - } - } - - private void lockedPrintStackTrace(PrintStreamOrWriter s) { // Guard against malicious overrides of Throwable.equals by // using a Set with identity equality semantics. Set dejaVu = Collections.newSetFromMap(new IdentityHashMap<>()); dejaVu.add(this); - // Print our stack trace - s.println(this); - StackTraceElement[] trace = getOurStackTrace(); - for (StackTraceElement traceElement : trace) - s.println("\tat " + traceElement); + synchronized(s.lock()) { + // Print our stack trace + s.println(this); + StackTraceElement[] trace = getOurStackTrace(); + for (StackTraceElement traceElement : trace) + s.println("\tat " + traceElement); - // Print suppressed exceptions, if any - for (Throwable se : getSuppressed()) - se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu); + // Print suppressed exceptions, if any + for (Throwable se : getSuppressed()) + se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu); - // Print cause, if any - Throwable ourCause = getCause(); - if (ourCause != null) - ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu); + // Print cause, if any + Throwable ourCause = getCause(); + if (ourCause != null) + ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu); + } } /** @@ -733,7 +720,7 @@ private void printEnclosedStackTrace(PrintStreamOrWriter s, String caption, String prefix, Set dejaVu) { - assert s.isLockedByCurrentThread(); + assert Thread.holdsLock(s.lock()); if (dejaVu.contains(this)) { s.println(prefix + caption + "[CIRCULAR REFERENCE: " + this + "]"); } else { @@ -785,15 +772,6 @@ private abstract static class PrintStreamOrWriter { /** Returns the object to be locked when using this StreamOrWriter */ abstract Object lock(); - boolean isLockedByCurrentThread() { - Object lock = lock(); - if (lock instanceof InternalLock locker) { - return locker.isHeldByCurrentThread(); - } else { - return Thread.holdsLock(lock); - } - } - /** Prints the specified string as a line on this StreamOrWriter */ abstract void println(Object o); } diff --git a/src/java.base/share/classes/jdk/internal/misc/InternalLock.java b/src/java.base/share/classes/jdk/internal/misc/InternalLock.java deleted file mode 100644 index 822b64f74ca6a..0000000000000 --- a/src/java.base/share/classes/jdk/internal/misc/InternalLock.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2021, 2024, 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.misc; - -import java.util.concurrent.locks.ReentrantLock; - -/** - * A reentrant mutual exclusion lock for internal use. The lock does not - * implement {@link java.util.concurrent.locks.Lock} or extend {@link - * java.util.concurrent.locks.ReentrantLock} so that it can be distinguished - * from lock objects accessible to subclasses of {@link java.io.Reader} and - * {@link java.io.Writer} (it is possible to create a Reader that uses a - * lock object of type ReentrantLock for example). - */ -public class InternalLock { - private static final boolean CAN_USE_INTERNAL_LOCK; - static { - String s = System.getProperty("jdk.io.useMonitors"); - if (s != null && s.equals("false")) { - CAN_USE_INTERNAL_LOCK = true; - } else { - CAN_USE_INTERNAL_LOCK = false; - } - } - - private final ReentrantLock lock; - - private InternalLock() { - this.lock = new ReentrantLock(); - } - - /** - * Returns a new InternalLock or null. - */ - public static InternalLock newLockOrNull() { - return (CAN_USE_INTERNAL_LOCK) ? new InternalLock() : null; - } - - /** - * Returns a new InternalLock or the given object. - */ - public static Object newLockOr(Object obj) { - return (CAN_USE_INTERNAL_LOCK) ? new InternalLock() : obj; - } - - public boolean tryLock() { - return lock.tryLock(); - } - - public void lock() { - lock.lock(); - } - - public void unlock() { - lock.unlock(); - } - - public boolean isHeldByCurrentThread() { - return lock.isHeldByCurrentThread(); - } -} diff --git a/src/java.base/share/classes/sun/nio/cs/StreamDecoder.java b/src/java.base/share/classes/sun/nio/cs/StreamDecoder.java index a2026744f04b5..124e41b77c9f7 100644 --- a/src/java.base/share/classes/sun/nio/cs/StreamDecoder.java +++ b/src/java.base/share/classes/sun/nio/cs/StreamDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, 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 @@ -44,8 +44,6 @@ import java.nio.charset.UnsupportedCharsetException; import java.util.Arrays; -import jdk.internal.misc.InternalLock; - public class StreamDecoder extends Reader { private static final int MIN_BYTE_BUFFER_SIZE = 32; @@ -121,178 +119,109 @@ public int read() throws IOException { return read0(); } + @SuppressWarnings("fallthrough") private int read0() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return lockedRead0(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - return lockedRead0(); + synchronized (lock) { + // Return the leftover char, if there is one + if (haveLeftoverChar) { + haveLeftoverChar = false; + return leftoverChar; } - } - } - - @SuppressWarnings("fallthrough") - private int lockedRead0() throws IOException { - // Return the leftover char, if there is one - if (haveLeftoverChar) { - haveLeftoverChar = false; - return leftoverChar; - } - // Convert more bytes - char[] cb = new char[2]; - int n = read(cb, 0, 2); - switch (n) { - case -1: - return -1; - case 2: - leftoverChar = cb[1]; - haveLeftoverChar = true; - // FALL THROUGH - case 1: - return cb[0]; - default: - assert false : n; - return -1; + // Convert more bytes + char[] cb = new char[2]; + int n = read(cb, 0, 2); + switch (n) { + case -1: + return -1; + case 2: + leftoverChar = cb[1]; + haveLeftoverChar = true; + // FALL THROUGH + case 1: + return cb[0]; + default: + assert false : n; + return -1; + } } } public int read(char[] cbuf, int offset, int length) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return lockedRead(cbuf, offset, length); - } finally { - locker.unlock(); + synchronized (lock) { + int off = offset; + int len = length; + + ensureOpen(); + if ((off < 0) || (off > cbuf.length) || (len < 0) || + ((off + len) > cbuf.length) || ((off + len) < 0)) { + throw new IndexOutOfBoundsException(); } - } else { - synchronized (lock) { - return lockedRead(cbuf, offset, length); + if (len == 0) + return 0; + + int n = 0; + + if (haveLeftoverChar) { + // Copy the leftover char into the buffer + cbuf[off] = leftoverChar; + off++; len--; + haveLeftoverChar = false; + n = 1; + if ((len == 0) || !implReady()) + // Return now if this is all we can produce w/o blocking + return n; } - } - } - private int lockedRead(char[] cbuf, int offset, int length) throws IOException { - int off = offset; - int len = length; + if (len == 1) { + // Treat single-character array reads just like read() + int c = read0(); + if (c == -1) + return (n == 0) ? -1 : n; + cbuf[off] = (char)c; + return n + 1; + } - ensureOpen(); - if ((off < 0) || (off > cbuf.length) || (len < 0) || - ((off + len) > cbuf.length) || ((off + len) < 0)) { - throw new IndexOutOfBoundsException(); - } - if (len == 0) - return 0; - - int n = 0; - - if (haveLeftoverChar) { - // Copy the leftover char into the buffer - cbuf[off] = leftoverChar; - off++; len--; - haveLeftoverChar = false; - n = 1; - if ((len == 0) || !implReady()) - // Return now if this is all we can produce w/o blocking - return n; - } + // Read remaining characters + int nr = implRead(cbuf, off, off + len); - if (len == 1) { - // Treat single-character array reads just like read() - int c = read0(); - if (c == -1) - return (n == 0) ? -1 : n; - cbuf[off] = (char)c; - return n + 1; + // At this point, n is either 1 if a leftover character was read, + // or 0 if no leftover character was read. If n is 1 and nr is -1, + // indicating EOF, then we don't return their sum as this loses data. + return (nr < 0) ? (n == 1 ? 1 : nr) : (n + nr); } - - // Read remaining characters - int nr = implRead(cbuf, off, off + len); - - // At this point, n is either 1 if a leftover character was read, - // or 0 if no leftover character was read. If n is 1 and nr is -1, - // indicating EOF, then we don't return their sum as this loses data. - return (nr < 0) ? (n == 1 ? 1 : nr) : (n + nr); } public boolean ready() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - return lockedReady(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - return lockedReady(); - } + synchronized (lock) { + ensureOpen(); + return haveLeftoverChar || implReady(); } } - private boolean lockedReady() throws IOException { - ensureOpen(); - return haveLeftoverChar || implReady(); - } - public void close() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { + if (closed) + return; try { - lockedClose(); + implClose(); } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - lockedClose(); + closed = true; } } } - private void lockedClose() throws IOException { - if (closed) - return; - try { - implClose(); - } finally { - closed = true; - } - } - private boolean isOpen() { return !closed; } public void fillZeroToPosition() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - lockedFillZeroToPosition(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - lockedFillZeroToPosition(); - } + synchronized (lock) { + Arrays.fill(bb.array(), bb.arrayOffset(), + bb.arrayOffset() + bb.position(), (byte)0); } } - private void lockedFillZeroToPosition() { - Arrays.fill(bb.array(), bb.arrayOffset(), bb.arrayOffset() + bb.position(), (byte)0); - } - // -- Charset-based stream decoder impl -- private final Charset cs; diff --git a/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java b/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java index 3a82030121abc..b580ad2f92157 100644 --- a/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java +++ b/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, 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 @@ -37,7 +37,6 @@ import java.nio.charset.CodingErrorAction; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; -import jdk.internal.misc.InternalLock; public final class StreamEncoder extends Writer { @@ -97,28 +96,14 @@ public String getEncoding() { } public void flushBuffer() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - lockedFlushBuffer(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - lockedFlushBuffer(); - } + synchronized (lock) { + if (isOpen()) + implFlushBuffer(); + else + throw new IOException("Stream closed"); } } - private void lockedFlushBuffer() throws IOException { - if (isOpen()) - implFlushBuffer(); - else - throw new IOException("Stream closed"); - } - public void write(int c) throws IOException { char[] cbuf = new char[1]; cbuf[0] = (char) c; @@ -126,30 +111,16 @@ public void write(int c) throws IOException { } public void write(char[] cbuf, int off, int len) throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - lockedWrite(cbuf, off, len); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - lockedWrite(cbuf, off, len); - } - } - } - - private void lockedWrite(char[] cbuf, int off, int len) throws IOException { - ensureOpen(); - if ((off < 0) || (off > cbuf.length) || (len < 0) || + synchronized (lock) { + ensureOpen(); + if ((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0)) { - throw new IndexOutOfBoundsException(); - } else if (len == 0) { - return; + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return; + } + implWrite(cbuf, off, len); } - implWrite(cbuf, off, len); } public void write(String str, int off, int len) throws IOException { @@ -164,76 +135,34 @@ public void write(String str, int off, int len) throws IOException { public void write(CharBuffer cb) throws IOException { int position = cb.position(); try { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - lockedWrite(cb); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - lockedWrite(cb); - } + synchronized (lock) { + ensureOpen(); + implWrite(cb); } } finally { cb.position(position); } } - private void lockedWrite(CharBuffer cb) throws IOException { - ensureOpen(); - implWrite(cb); - } - public void flush() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); - try { - lockedFlush(); - } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - lockedFlush(); - } + synchronized (lock) { + ensureOpen(); + implFlush(); } } - private void lockedFlush() throws IOException { - ensureOpen(); - implFlush(); - } - public void close() throws IOException { - Object lock = this.lock; - if (lock instanceof InternalLock locker) { - locker.lock(); + synchronized (lock) { + if (closed) + return; try { - lockedClose(); + implClose(); } finally { - locker.unlock(); - } - } else { - synchronized (lock) { - lockedClose(); + closed = true; } } } - private void lockedClose() throws IOException { - if (closed) - return; - try { - implClose(); - } finally { - closed = true; - } - } - private boolean isOpen() { return !closed; } From d3d1e3a58f7e395e0c3c5785726e9d5482fa5f59 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 13 Nov 2024 10:56:13 -0800 Subject: [PATCH 3/8] 8343039: Remove JavaIOPrint{Stream,Writer}Access and the use thereof --- .../share/classes/java/io/PrintStream.java | 10 ------ .../share/classes/java/io/PrintWriter.java | 10 ------ .../share/classes/java/lang/Throwable.java | 5 ++- .../access/JavaIOPrintStreamAccess.java | 31 ------------------- .../access/JavaIOPrintWriterAccess.java | 31 ------------------- .../jdk/internal/access/SharedSecrets.java | 28 ----------------- 6 files changed, 2 insertions(+), 113 deletions(-) delete mode 100644 src/java.base/share/classes/jdk/internal/access/JavaIOPrintStreamAccess.java delete mode 100644 src/java.base/share/classes/jdk/internal/access/JavaIOPrintWriterAccess.java diff --git a/src/java.base/share/classes/java/io/PrintStream.java b/src/java.base/share/classes/java/io/PrintStream.java index 11b71b5d2ae11..1e1d53b981f8d 100644 --- a/src/java.base/share/classes/java/io/PrintStream.java +++ b/src/java.base/share/classes/java/io/PrintStream.java @@ -30,8 +30,6 @@ import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; -import jdk.internal.access.JavaIOPrintStreamAccess; -import jdk.internal.access.SharedSecrets; /** * A {@code PrintStream} adds functionality to another output stream, @@ -1377,12 +1375,4 @@ public PrintStream append(char c) { public Charset charset() { return charset; } - - static { - SharedSecrets.setJavaIOCPrintStreamAccess(new JavaIOPrintStreamAccess() { - public Object lock(PrintStream ps) { - return ps; - } - }); - } } diff --git a/src/java.base/share/classes/java/io/PrintWriter.java b/src/java.base/share/classes/java/io/PrintWriter.java index 07c1514f26143..ea430a9401fce 100644 --- a/src/java.base/share/classes/java/io/PrintWriter.java +++ b/src/java.base/share/classes/java/io/PrintWriter.java @@ -31,8 +31,6 @@ 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; /** * Prints formatted representations of objects to a text-output stream. This @@ -1163,12 +1161,4 @@ public PrintWriter append(char c) { write(c); return this; } - - static { - SharedSecrets.setJavaIOCPrintWriterAccess(new JavaIOPrintWriterAccess() { - public Object lock(PrintWriter pw) { - return pw.lock; - } - }); - } } diff --git a/src/java.base/share/classes/java/lang/Throwable.java b/src/java.base/share/classes/java/lang/Throwable.java index ca2c4071b3df5..8c0ce29dbeefc 100644 --- a/src/java.base/share/classes/java/lang/Throwable.java +++ b/src/java.base/share/classes/java/lang/Throwable.java @@ -27,7 +27,6 @@ import java.io.*; import java.util.*; -import jdk.internal.access.SharedSecrets; import jdk.internal.event.ThrowableTracer; /** @@ -784,7 +783,7 @@ private static class WrappedPrintStream extends PrintStreamOrWriter { } Object lock() { - return SharedSecrets.getJavaIOPrintStreamAccess().lock(printStream); + return printStream; } void println(Object o) { @@ -800,7 +799,7 @@ private static class WrappedPrintWriter extends PrintStreamOrWriter { } Object lock() { - return SharedSecrets.getJavaIOPrintWriterAccess().lock(printWriter); + return printWriter; } void println(Object o) { diff --git a/src/java.base/share/classes/jdk/internal/access/JavaIOPrintStreamAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaIOPrintStreamAccess.java deleted file mode 100644 index ec205e27dca19..0000000000000 --- a/src/java.base/share/classes/jdk/internal/access/JavaIOPrintStreamAccess.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2020, 2022, 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.io.PrintStream; - -public interface JavaIOPrintStreamAccess { - Object lock(PrintStream ps); -} diff --git a/src/java.base/share/classes/jdk/internal/access/JavaIOPrintWriterAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaIOPrintWriterAccess.java deleted file mode 100644 index 8be54a76b0afb..0000000000000 --- a/src/java.base/share/classes/jdk/internal/access/JavaIOPrintWriterAccess.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2020, 2022, 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.io.PrintWriter; - -public interface JavaIOPrintWriterAccess { - Object lock(PrintWriter pw); -} diff --git a/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java b/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java index 5acafe01a8908..c29d0dd01a59d 100644 --- a/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java +++ b/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java @@ -71,8 +71,6 @@ public class SharedSecrets { private static JavaLangRefAccess javaLangRefAccess; private static JavaLangReflectAccess javaLangReflectAccess; private static JavaIOAccess javaIOAccess; - private static JavaIOPrintStreamAccess javaIOPrintStreamAccess; - private static JavaIOPrintWriterAccess javaIOPrintWriterAccess; private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess; private static JavaIOFilePermissionAccess javaIOFilePermissionAccess; private static JavaIORandomAccessFileAccess javaIORandomAccessFileAccess; @@ -288,32 +286,6 @@ public static JavaIOAccess getJavaIOAccess() { return access; } - public static void setJavaIOCPrintWriterAccess(JavaIOPrintWriterAccess a) { - javaIOPrintWriterAccess = a; - } - - public static JavaIOPrintWriterAccess getJavaIOPrintWriterAccess() { - var access = javaIOPrintWriterAccess; - if (access == null) { - ensureClassInitialized(PrintWriter.class); - access = javaIOPrintWriterAccess; - } - return access; - } - - public static void setJavaIOCPrintStreamAccess(JavaIOPrintStreamAccess a) { - javaIOPrintStreamAccess = a; - } - - public static JavaIOPrintStreamAccess getJavaIOPrintStreamAccess() { - var access = javaIOPrintStreamAccess; - if (access == null) { - ensureClassInitialized(PrintStream.class); - access = javaIOPrintStreamAccess; - } - return access; - } - public static void setJavaIOFileDescriptorAccess(JavaIOFileDescriptorAccess jiofda) { javaIOFileDescriptorAccess = jiofda; } From 9417b53da55bcc3abb5f399222319edf04414623 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 13 Nov 2024 12:01:11 -0800 Subject: [PATCH 4/8] 8343039: Address reviewer comments --- src/java.base/share/classes/java/io/BufferedInputStream.java | 1 + src/java.base/share/classes/java/io/BufferedOutputStream.java | 4 ++-- src/java.base/share/classes/java/io/PrintWriter.java | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/java/io/BufferedInputStream.java b/src/java.base/share/classes/java/io/BufferedInputStream.java index 3661be8236c57..5ca55d838ae34 100644 --- a/src/java.base/share/classes/java/io/BufferedInputStream.java +++ b/src/java.base/share/classes/java/io/BufferedInputStream.java @@ -239,6 +239,7 @@ public BufferedInputStream(InputStream in, int size) { } initialSize = size; if (getClass() == BufferedInputStream.class) { + // lazily create buffer when not subclassed buf = EMPTY; } else { buf = new byte[size]; diff --git a/src/java.base/share/classes/java/io/BufferedOutputStream.java b/src/java.base/share/classes/java/io/BufferedOutputStream.java index 460689bd6b8c6..11d05f91f3e7f 100644 --- a/src/java.base/share/classes/java/io/BufferedOutputStream.java +++ b/src/java.base/share/classes/java/io/BufferedOutputStream.java @@ -85,9 +85,9 @@ private BufferedOutputStream(OutputStream out, int initialSize, int maxSize) { throw new IllegalArgumentException("Buffer size <= 0"); } - this.buf = new byte[initialSize]; // resizable if initialSize < maxSize if (getClass() == BufferedOutputStream.class) { - this.buf = new byte[initialSize]; // resizable + // resizable if initialSize < maxSize + this.buf = new byte[initialSize]; } else { this.buf = new byte[maxSize]; } diff --git a/src/java.base/share/classes/java/io/PrintWriter.java b/src/java.base/share/classes/java/io/PrintWriter.java index ea430a9401fce..7051411332650 100644 --- a/src/java.base/share/classes/java/io/PrintWriter.java +++ b/src/java.base/share/classes/java/io/PrintWriter.java @@ -419,7 +419,6 @@ public void flush() { * @see #checkError() */ public void close() { - Object lock = this.lock; synchronized (lock) { try { if (out != null) { From f5548c1b8dd920dea8b66246588e98ab8c2cbc5e Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 13 Nov 2024 12:11:47 -0800 Subject: [PATCH 5/8] 8343039: Remove InternalLock reference from java/lang/ProcessBuilder/Basic.java --- test/jdk/java/lang/ProcessBuilder/Basic.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/test/jdk/java/lang/ProcessBuilder/Basic.java b/test/jdk/java/lang/ProcessBuilder/Basic.java index 382df89050cc1..909c90b46f546 100644 --- a/test/jdk/java/lang/ProcessBuilder/Basic.java +++ b/test/jdk/java/lang/ProcessBuilder/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -2865,15 +2865,6 @@ static void THROWS(Class k, Fun... fs) { static boolean isLocked(BufferedInputStream bis) throws Exception { Field lockField = BufferedInputStream.class.getDeclaredField("lock"); lockField.setAccessible(true); - var lock = (jdk.internal.misc.InternalLock) lockField.get(bis); - if (lock != null) { - if (lock.tryLock()) { - lock.unlock(); - return false; - } else { - return true; - } - } return new Thread() { volatile boolean unlocked; From 2034b5db0cc0eddf23ef1d7cb8b68c2e51e80cf7 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 13 Nov 2024 12:28:41 -0800 Subject: [PATCH 6/8] 8343039: Remove java.base/jdk.internal.misc from @modules in test java/lang/ProcessBuilder/Basic.java --- test/jdk/java/lang/ProcessBuilder/Basic.java | 1 - 1 file changed, 1 deletion(-) diff --git a/test/jdk/java/lang/ProcessBuilder/Basic.java b/test/jdk/java/lang/ProcessBuilder/Basic.java index 909c90b46f546..cbca26e213e4f 100644 --- a/test/jdk/java/lang/ProcessBuilder/Basic.java +++ b/test/jdk/java/lang/ProcessBuilder/Basic.java @@ -32,7 +32,6 @@ * @summary Basic tests for Process and Environment Variable code * @modules java.base/java.lang:open * java.base/java.io:open - * java.base/jdk.internal.misc * @requires !vm.musl * @requires vm.flagless * @library /test/lib From 0b68ed082fa4ddee0b66a93223fb09e3c0ef3d4c Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 13 Nov 2024 13:36:13 -0800 Subject: [PATCH 7/8] 8343039: Remove failing getDeclaredField call from test java/lang/ProcessBuilder/Basic.java --- test/jdk/java/lang/ProcessBuilder/Basic.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/jdk/java/lang/ProcessBuilder/Basic.java b/test/jdk/java/lang/ProcessBuilder/Basic.java index cbca26e213e4f..ba2bedd2fddc7 100644 --- a/test/jdk/java/lang/ProcessBuilder/Basic.java +++ b/test/jdk/java/lang/ProcessBuilder/Basic.java @@ -2862,8 +2862,6 @@ static void THROWS(Class k, Fun... fs) { else unexpected(t);}} static boolean isLocked(BufferedInputStream bis) throws Exception { - Field lockField = BufferedInputStream.class.getDeclaredField("lock"); - lockField.setAccessible(true); return new Thread() { volatile boolean unlocked; From 15bf969a1b3e7c7cc60d6da9956c6af6b2262ef8 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Thu, 14 Nov 2024 08:37:45 -0800 Subject: [PATCH 8/8] 8343039: Change "resizble" comment in BOS --- src/java.base/share/classes/java/io/BufferedOutputStream.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/io/BufferedOutputStream.java b/src/java.base/share/classes/java/io/BufferedOutputStream.java index 11d05f91f3e7f..2ad9adad5ad25 100644 --- a/src/java.base/share/classes/java/io/BufferedOutputStream.java +++ b/src/java.base/share/classes/java/io/BufferedOutputStream.java @@ -86,7 +86,7 @@ private BufferedOutputStream(OutputStream out, int initialSize, int maxSize) { } if (getClass() == BufferedOutputStream.class) { - // resizable if initialSize < maxSize + // resizable when not sub-classed this.buf = new byte[initialSize]; } else { this.buf = new byte[maxSize];