mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
8343039: Remove jdk.internal.misc.InternalLock and usages from java.io
Reviewed-by: liach, alanb
This commit is contained in:
parent
3c38ed4128
commit
0b9b82af03
19 changed files with 548 additions and 1789 deletions
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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,9 +27,7 @@ package java.lang;
|
|||
|
||||
import java.io.*;
|
||||
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 +687,27 @@ public class Throwable implements Serializable {
|
|||
}
|
||||
|
||||
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<Throwable> 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 +719,7 @@ public class Throwable implements Serializable {
|
|||
String caption,
|
||||
String prefix,
|
||||
Set<Throwable> dejaVu) {
|
||||
assert s.isLockedByCurrentThread();
|
||||
assert Thread.holdsLock(s.lock());
|
||||
if (dejaVu.contains(this)) {
|
||||
s.println(prefix + caption + "[CIRCULAR REFERENCE: " + this + "]");
|
||||
} else {
|
||||
|
@ -785,15 +771,6 @@ public class Throwable implements Serializable {
|
|||
/** 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);
|
||||
}
|
||||
|
@ -806,7 +783,7 @@ public class Throwable implements Serializable {
|
|||
}
|
||||
|
||||
Object lock() {
|
||||
return SharedSecrets.getJavaIOPrintStreamAccess().lock(printStream);
|
||||
return printStream;
|
||||
}
|
||||
|
||||
void println(Object o) {
|
||||
|
@ -822,7 +799,7 @@ public class Throwable implements Serializable {
|
|||
}
|
||||
|
||||
Object lock() {
|
||||
return SharedSecrets.getJavaIOPrintWriterAccess().lock(printWriter);
|
||||
return printWriter;
|
||||
}
|
||||
|
||||
void println(Object o) {
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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 class SharedSecrets {
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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.IllegalCharsetNameException;
|
|||
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,151 +119,95 @@ public class StreamDecoder extends Reader {
|
|||
return read0();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("fallthrough")
|
||||
private int lockedRead0() throws IOException {
|
||||
// Return the leftover char, if there is one
|
||||
if (haveLeftoverChar) {
|
||||
haveLeftoverChar = false;
|
||||
return leftoverChar;
|
||||
}
|
||||
private int read0() throws IOException {
|
||||
synchronized (lock) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
private int lockedRead(char[] cbuf, int offset, int length) throws IOException {
|
||||
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();
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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();
|
||||
closed = true;
|
||||
}
|
||||
} else {
|
||||
synchronized (lock) {
|
||||
lockedClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void lockedClose() throws IOException {
|
||||
if (closed)
|
||||
return;
|
||||
try {
|
||||
implClose();
|
||||
} finally {
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,25 +216,12 @@ public class StreamDecoder extends Reader {
|
|||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -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.CoderResult;
|
|||
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 final class StreamEncoder extends Writer {
|
|||
}
|
||||
|
||||
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 final class StreamEncoder extends Writer {
|
|||
}
|
||||
|
||||
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,73 +135,31 @@ public final class StreamEncoder extends Writer {
|
|||
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();
|
||||
closed = true;
|
||||
}
|
||||
} else {
|
||||
synchronized (lock) {
|
||||
lockedClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void lockedClose() throws IOException {
|
||||
if (closed)
|
||||
return;
|
||||
try {
|
||||
implClose();
|
||||
} finally {
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue