8343039: Remove jdk.internal.misc.InternalLock and usages from java.io

Reviewed-by: liach, alanb
This commit is contained in:
Brian Burkhalter 2024-11-15 16:11:34 +00:00
parent 3c38ed4128
commit 0b9b82af03
19 changed files with 548 additions and 1789 deletions

View file

@ -28,7 +28,6 @@ package java.io;
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;
@ -243,12 +239,9 @@ public class BufferedInputStream extends FilterInputStream {
}
initialSize = size;
if (getClass() == BufferedInputStream.class) {
// use internal lock and lazily create buffer when not subclassed
lock = InternalLock.newLockOrNull();
// lazily create buffer when not subclassed
buf = EMPTY;
} else {
// use monitors and eagerly create buffer when subclassed
lock = null;
buf = new byte[size];
}
}
@ -256,7 +249,7 @@ public class BufferedInputStream extends FilterInputStream {
/**
* 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 +303,7 @@ public class BufferedInputStream extends FilterInputStream {
* 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 +375,7 @@ public class BufferedInputStream extends FilterInputStream {
* 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 +407,7 @@ public class BufferedInputStream extends FilterInputStream {
* {@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 +448,7 @@ public class BufferedInputStream extends FilterInputStream {
* 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 +464,7 @@ public class BufferedInputStream extends FilterInputStream {
* 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 +485,7 @@ public class BufferedInputStream extends FilterInputStream {
* 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 +531,8 @@ public class BufferedInputStream extends FilterInputStream {
}
@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) {

View file

@ -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.
*/
@ -90,12 +86,9 @@ public class BufferedOutputStream extends FilterOutputStream {
}
if (getClass() == BufferedOutputStream.class) {
// use InternalLock and resizable buffer when not sub-classed
this.lock = InternalLock.newLockOrNull();
this.buf = new byte[initialSize]; // resizable
// resizable when not sub-classed
this.buf = new byte[initialSize];
} else {
// use monitors and no resizing when sub-classed
this.lock = null;
this.buf = new byte[maxSize];
}
this.maxBufSize = maxSize;
@ -136,8 +129,6 @@ public class BufferedOutputStream extends FilterOutputStream {
* 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 +148,7 @@ public class BufferedOutputStream extends FilterOutputStream {
* @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 +174,7 @@ public class BufferedOutputStream extends FilterOutputStream {
* @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 +199,7 @@ public class BufferedOutputStream extends FilterOutputStream {
* @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();
}

View file

@ -32,7 +32,6 @@ import java.util.Spliterator;
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 @@ public class BufferedReader extends Reader {
* @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,38 +281,24 @@ public class BufferedReader extends Reader {
* @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();
synchronized (lock) {
ensureOpen();
Objects.checkFromIndexSize(off, len, cbuf.length);
if (len == 0) {
return 0;
}
} else {
synchronized (lock) {
return implRead(cbuf, off, len);
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;
}
}
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;
}
return n;
}
/**
* Reads a line of text. A line is considered to be terminated by any one
* of a line feed ('\n'), a carriage return ('\r'), a carriage return
@ -347,81 +318,67 @@ public class BufferedReader extends Reader {
* @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;
/* 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;
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;
startChar = nextChar;
nextChar = i;
/* Skip a leftover '\n', if necessary */
if (omitLF && (cb[nextChar] == '\n'))
nextChar++;
skipLF = false;
omitLF = false;
if (eol) {
String str;
if (s == null) {
str = new String(cb, startChar, i - startChar);
} else {
s.append(cb, startChar, i - startChar);
str = s.toString();
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;
}
}
nextChar++;
if (c == '\r') {
skipLF = true;
}
return str;
}
if (s == null)
s = new StringBuilder(DEFAULT_EXPECTED_LINE_LENGTH);
s.append(cb, startChar, i - startChar);
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;
}
return str;
}
if (s == null)
s = new StringBuilder(DEFAULT_EXPECTED_LINE_LENGTH);
s.append(cb, startChar, i - startChar);
}
}
}
@ -450,47 +407,33 @@ public class BufferedReader extends Reader {
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 @@ public class BufferedReader extends Reader {
* @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 class BufferedReader extends Reader {
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 @@ public class BufferedReader extends Reader {
* 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;
}
}

View file

@ -27,7 +27,6 @@ package java.io;
import java.util.Arrays;
import java.util.Objects;
import jdk.internal.misc.InternalLock;
import jdk.internal.misc.VM;
/**
@ -162,58 +161,30 @@ public class BufferedWriter extends Writer {
* 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 @@ public class BufferedWriter extends Writer {
* @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();
synchronized (lock) {
ensureOpen();
Objects.checkFromIndexSize(off, len, cbuf.length);
if (len == 0) {
return;
}
} else {
synchronized (lock) {
implWrite(cbuf, off, len);
}
}
}
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,32 +269,18 @@ public class BufferedWriter extends Writer {
* @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();
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();
}
} else {
synchronized (lock) {
implWrite(s, off, len);
}
}
}
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();
}
}
@ -358,52 +301,24 @@ public class BufferedWriter extends Writer {
* @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();
}
}
}
private void implFlush() throws IOException {
flushBuffer();
out.flush();
}
public void close() throws IOException {
Object lock = this.lock;
if (lock instanceof InternalLock locker) {
locker.lock();
try {
implClose();
} finally {
locker.unlock();
}
} else {
synchronized (lock) {
implClose();
}
synchronized (lock) {
flushBuffer();
out.flush();
}
}
@SuppressWarnings("try")
private void implClose() throws IOException {
if (out == null) {
return;
}
try (Writer w = out) {
flushBuffer();
} finally {
out = null;
cb = null;
public void close() throws IOException {
synchronized (lock) {
if (out == null) {
return;
}
try (Writer w = out) {
flushBuffer();
} finally {
out = null;
cb = null;
}
}
}
}

View file

@ -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 @@ package java.io;
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 @@ import sun.nio.cs.StreamDecoder;
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 @@ public class InputStreamReader extends 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 class InputStreamReader extends Reader {
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 class InputStreamReader extends Reader {
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 class InputStreamReader extends Reader {
super(in);
if (dec == null)
throw new NullPointerException("charset decoder");
sd = StreamDecoder.forInputStreamReader(in, lockFor(this), dec);
sd = StreamDecoder.forInputStreamReader(in, this, dec);
}
/**

View file

@ -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 @@ package java.io;
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 @@ import sun.nio.cs.StreamEncoder;
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 class OutputStreamWriter extends Writer {
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 class OutputStreamWriter extends Writer {
@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 class OutputStreamWriter extends Writer {
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 class OutputStreamWriter extends Writer {
super(out);
if (enc == null)
throw new NullPointerException("charset encoder");
se = StreamEncoder.forOutputStreamWriter(out, lockFor(this), enc);
se = StreamEncoder.forOutputStreamWriter(out, this, enc);
}
/**

View file

@ -30,9 +30,6 @@ import java.util.Locale;
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;
import jdk.internal.misc.InternalLock;
/**
* A {@code PrintStream} adds functionality to another output stream,
@ -67,9 +64,6 @@ import jdk.internal.misc.InternalLock;
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 +111,6 @@ public class PrintStream extends FilterOutputStream
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 +207,6 @@ public class PrintStream extends FilterOutputStream
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;
}
}
/**
@ -420,30 +400,17 @@ public class PrintStream extends FilterOutputStream
*/
@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 */
/**
@ -454,33 +421,20 @@ public class PrintStream extends FilterOutputStream
*/
@Override
public void close() {
if (lock != null) {
lock.lock();
try {
implClose();
} finally {
lock.unlock();
synchronized (this) {
if (!closing) {
closing = true;
try {
textOut.close();
out.close();
}
catch (IOException x) {
trouble = true;
}
textOut = null;
charOut = null;
out = null;
}
} else {
synchronized (this) {
implClose();
}
}
}
private void implClose() {
if (!closing) {
closing = true;
try {
textOut.close();
out.close();
}
catch (IOException x) {
trouble = true;
}
textOut = null;
charOut = null;
out = null;
}
}
@ -547,17 +501,11 @@ public class PrintStream extends FilterOutputStream
@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) {
@ -568,13 +516,6 @@ public class PrintStream extends FilterOutputStream
}
}
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
@ -593,17 +534,11 @@ public class PrintStream extends FilterOutputStream
@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) {
@ -614,14 +549,6 @@ public class PrintStream extends FilterOutputStream
}
}
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
@ -686,16 +613,17 @@ public class PrintStream extends FilterOutputStream
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) {
@ -705,37 +633,20 @@ public class PrintStream extends FilterOutputStream
}
}
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) {
@ -746,29 +657,15 @@ public class PrintStream extends FilterOutputStream
}
}
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) {
@ -779,32 +676,20 @@ public class PrintStream extends FilterOutputStream
}
}
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) {
@ -815,29 +700,15 @@ public class PrintStream extends FilterOutputStream
}
}
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) {
@ -848,15 +719,6 @@ public class PrintStream extends FilterOutputStream
}
}
private void implNewLine() throws IOException {
ensureOpen();
textOut.newLine();
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush)
out.flush();
}
/* Methods that do not terminate lines */
/**
@ -1314,17 +1176,11 @@ public class PrintStream extends FilterOutputStream
*/
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();
@ -1334,13 +1190,6 @@ public class PrintStream extends FilterOutputStream
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.
@ -1383,17 +1232,11 @@ public class PrintStream extends FilterOutputStream
*/
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();
@ -1403,13 +1246,6 @@ public class PrintStream extends FilterOutputStream
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.
*
@ -1511,13 +1347,4 @@ public class PrintStream extends FilterOutputStream
public Charset charset() {
return charset;
}
static {
SharedSecrets.setJavaIOCPrintStreamAccess(new JavaIOPrintStreamAccess() {
public Object lock(PrintStream ps) {
Object lock = ps.lock;
return (lock != null) ? lock : ps;
}
});
}
}

View file

@ -31,9 +31,6 @@ import java.util.Locale;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import jdk.internal.access.JavaIOPrintWriterAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.InternalLock;
/**
* Prints formatted representations of objects to a text-output stream. This
@ -377,27 +374,13 @@ public class PrintWriter extends Writer {
* @see #checkError()
*/
public void flush() {
Object lock = this.lock;
if (lock instanceof InternalLock locker) {
locker.lock();
synchronized (lock) {
try {
implFlush();
} finally {
locker.unlock();
ensureOpen();
out.flush();
} catch (IOException x) {
trouble = true;
}
} else {
synchronized (lock) {
implFlush();
}
}
}
private void implFlush() {
try {
ensureOpen();
out.flush();
} catch (IOException x) {
trouble = true;
}
}
@ -408,29 +391,15 @@ public class PrintWriter extends Writer {
* @see #checkError()
*/
public void close() {
Object lock = this.lock;
if (lock instanceof InternalLock locker) {
locker.lock();
synchronized (lock) {
try {
implClose();
} finally {
locker.unlock();
if (out != null) {
out.close();
out = null;
}
} catch (IOException x) {
trouble = true;
}
} else {
synchronized (lock) {
implClose();
}
}
}
private void implClose() {
try {
if (out != null) {
out.close();
out = null;
}
} catch (IOException x) {
trouble = true;
}
}
@ -487,29 +456,15 @@ public class PrintWriter extends Writer {
* @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();
ensureOpen();
out.write(c);
} catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
} catch (IOException x) {
trouble = true;
}
} else {
synchronized (lock) {
implWrite(c);
}
}
}
private void implWrite(int c) {
try {
ensureOpen();
out.write(c);
} catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
} catch (IOException x) {
trouble = true;
}
}
@ -525,29 +480,15 @@ public class PrintWriter extends Writer {
* 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;
}
}
@ -572,29 +513,15 @@ public class PrintWriter extends Writer {
* 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();
ensureOpen();
out.write(s, off, len);
} catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
} catch (IOException x) {
trouble = true;
}
} else {
synchronized (lock) {
implWrite(s, off, len);
}
}
}
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;
}
}
@ -608,31 +535,17 @@ public class PrintWriter extends Writer {
}
private void newLine() {
Object lock = this.lock;
if (lock instanceof InternalLock locker) {
locker.lock();
synchronized (lock) {
try {
implNewLine();
} finally {
locker.unlock();
ensureOpen();
out.write(System.lineSeparator());
if (autoFlush)
out.flush();
} catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
} catch (IOException x) {
trouble = true;
}
} else {
synchronized (lock) {
implNewLine();
}
}
}
private void implNewLine() {
try {
ensureOpen();
out.write(System.lineSeparator());
if (autoFlush)
out.flush();
} catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
} catch (IOException x) {
trouble = true;
}
}
@ -788,20 +701,9 @@ public class PrintWriter extends Writer {
* @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();
}
}
@ -813,20 +715,9 @@ public class PrintWriter extends Writer {
* @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();
}
}
@ -838,20 +729,9 @@ public class PrintWriter extends Writer {
* @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();
}
}
@ -863,20 +743,9 @@ public class PrintWriter extends Writer {
* @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();
}
}
@ -888,20 +757,9 @@ public class PrintWriter extends Writer {
* @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();
}
}
@ -913,20 +771,9 @@ public class PrintWriter extends Writer {
* @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();
}
}
@ -938,20 +785,9 @@ public class PrintWriter extends Writer {
* @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();
}
}
@ -963,20 +799,9 @@ public class PrintWriter extends Writer {
* @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();
}
}
@ -991,20 +816,9 @@ public class PrintWriter extends Writer {
*/
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();
}
}
@ -1150,38 +964,24 @@ public class PrintWriter extends Writer {
* @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
@ -1224,37 +1024,23 @@ public class PrintWriter extends Writer {
* @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.
*
@ -1346,12 +1132,4 @@ public class PrintWriter extends Writer {
write(c);
return this;
}
static {
SharedSecrets.setJavaIOCPrintWriterAccess(new JavaIOPrintWriterAccess() {
public Object lock(PrintWriter pw) {
return pw.lock;
}
});
}
}

View file

@ -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 @@ package java.io;
import java.util.Arrays;
import java.util.Objects;
import jdk.internal.misc.InternalLock;
/**
* A {@code PushbackInputStream} adds
@ -54,10 +53,6 @@ import jdk.internal.misc.InternalLock;
* @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 class PushbackInputStream extends FilterInputStream {
}
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 class PushbackInputStream extends FilterInputStream {
*
* @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

View file

@ -28,7 +28,6 @@ package java.io;
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 @@ public abstract class Reader implements Readable, Closeable {
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,35 +413,21 @@ public abstract class Reader implements Readable, Closeable {
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);
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;
}
return n - r;
}
}
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;
}
/**
* Tells whether this stream is ready to be read.
*

View file

@ -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 @@ public abstract class Writer implements Appendable, Closeable, Flushable {
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 @@ public abstract class Writer implements Appendable, Closeable, Flushable {
* 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,35 +275,21 @@ public abstract class Writer implements Appendable, Closeable, Flushable {
* 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);
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];
}
str.getChars(off, (off + len), cbuf, 0);
write(cbuf, 0, 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];
}
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);
}
/**
* Appends the specified character sequence to this writer.
*