mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +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.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import jdk.internal.misc.InternalLock;
|
|
||||||
import jdk.internal.misc.Unsafe;
|
import jdk.internal.misc.Unsafe;
|
||||||
import jdk.internal.util.ArraysSupport;
|
import jdk.internal.util.ArraysSupport;
|
||||||
|
|
||||||
|
@ -74,9 +73,6 @@ public class BufferedInputStream extends FilterInputStream {
|
||||||
private static final long BUF_OFFSET
|
private static final long BUF_OFFSET
|
||||||
= U.objectFieldOffset(BufferedInputStream.class, "buf");
|
= 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)
|
// initial buffer size (DEFAULT_BUFFER_SIZE or size specified to constructor)
|
||||||
private final int initialSize;
|
private final int initialSize;
|
||||||
|
|
||||||
|
@ -243,12 +239,9 @@ public class BufferedInputStream extends FilterInputStream {
|
||||||
}
|
}
|
||||||
initialSize = size;
|
initialSize = size;
|
||||||
if (getClass() == BufferedInputStream.class) {
|
if (getClass() == BufferedInputStream.class) {
|
||||||
// use internal lock and lazily create buffer when not subclassed
|
// lazily create buffer when not subclassed
|
||||||
lock = InternalLock.newLockOrNull();
|
|
||||||
buf = EMPTY;
|
buf = EMPTY;
|
||||||
} else {
|
} else {
|
||||||
// use monitors and eagerly create buffer when subclassed
|
|
||||||
lock = null;
|
|
||||||
buf = new byte[size];
|
buf = new byte[size];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,7 +249,7 @@ public class BufferedInputStream extends FilterInputStream {
|
||||||
/**
|
/**
|
||||||
* Fills the buffer with more data, taking into account
|
* Fills the buffer with more data, taking into account
|
||||||
* shuffling and other tricks for dealing with marks.
|
* 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,
|
* This method also assumes that all data has already been read in,
|
||||||
* hence pos > count.
|
* hence pos > count.
|
||||||
*/
|
*/
|
||||||
|
@ -310,22 +303,7 @@ public class BufferedInputStream extends FilterInputStream {
|
||||||
* or an I/O error occurs.
|
* or an I/O error occurs.
|
||||||
* @see java.io.FilterInputStream#in
|
* @see java.io.FilterInputStream#in
|
||||||
*/
|
*/
|
||||||
public int read() throws IOException {
|
public synchronized 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 {
|
|
||||||
if (pos >= count) {
|
if (pos >= count) {
|
||||||
fill();
|
fill();
|
||||||
if (pos >= count)
|
if (pos >= count)
|
||||||
|
@ -397,22 +375,7 @@ public class BufferedInputStream extends FilterInputStream {
|
||||||
* or an I/O error occurs.
|
* or an I/O error occurs.
|
||||||
* @throws IndexOutOfBoundsException {@inheritDoc}
|
* @throws IndexOutOfBoundsException {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public int read(byte[] b, int off, int len) throws IOException {
|
public synchronized 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 {
|
|
||||||
ensureOpen();
|
ensureOpen();
|
||||||
if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
|
if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
|
||||||
throw new IndexOutOfBoundsException();
|
throw new IndexOutOfBoundsException();
|
||||||
|
@ -444,22 +407,7 @@ public class BufferedInputStream extends FilterInputStream {
|
||||||
* {@code in.skip(n)} throws an IOException,
|
* {@code in.skip(n)} throws an IOException,
|
||||||
* or an I/O error occurs.
|
* or an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
public long skip(long n) throws IOException {
|
public synchronized 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 {
|
|
||||||
ensureOpen();
|
ensureOpen();
|
||||||
if (n <= 0) {
|
if (n <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -500,22 +448,7 @@ public class BufferedInputStream extends FilterInputStream {
|
||||||
* invoking its {@link #close()} method,
|
* invoking its {@link #close()} method,
|
||||||
* or an I/O error occurs.
|
* or an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
public int available() throws IOException {
|
public synchronized 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 {
|
|
||||||
int n = count - pos;
|
int n = count - pos;
|
||||||
int avail = getInIfOpen().available();
|
int avail = getInIfOpen().available();
|
||||||
return n > (Integer.MAX_VALUE - avail)
|
return n > (Integer.MAX_VALUE - avail)
|
||||||
|
@ -531,22 +464,7 @@ public class BufferedInputStream extends FilterInputStream {
|
||||||
* the mark position becomes invalid.
|
* the mark position becomes invalid.
|
||||||
* @see java.io.BufferedInputStream#reset()
|
* @see java.io.BufferedInputStream#reset()
|
||||||
*/
|
*/
|
||||||
public void mark(int readlimit) {
|
public synchronized 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) {
|
|
||||||
marklimit = readlimit;
|
marklimit = readlimit;
|
||||||
markpos = pos;
|
markpos = pos;
|
||||||
}
|
}
|
||||||
|
@ -567,22 +485,7 @@ public class BufferedInputStream extends FilterInputStream {
|
||||||
* method, or an I/O error occurs.
|
* method, or an I/O error occurs.
|
||||||
* @see java.io.BufferedInputStream#mark(int)
|
* @see java.io.BufferedInputStream#mark(int)
|
||||||
*/
|
*/
|
||||||
public void reset() throws IOException {
|
public synchronized void reset() throws IOException {
|
||||||
if (lock != null) {
|
|
||||||
lock.lock();
|
|
||||||
try {
|
|
||||||
implReset();
|
|
||||||
} finally {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (this) {
|
|
||||||
implReset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void implReset() throws IOException {
|
|
||||||
ensureOpen();
|
ensureOpen();
|
||||||
if (markpos < 0)
|
if (markpos < 0)
|
||||||
throw new IOException("Resetting to invalid mark");
|
throw new IOException("Resetting to invalid mark");
|
||||||
|
@ -628,23 +531,8 @@ public class BufferedInputStream extends FilterInputStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long transferTo(OutputStream out) throws IOException {
|
public synchronized long transferTo(OutputStream out) throws IOException {
|
||||||
Objects.requireNonNull(out, "out");
|
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) {
|
if (getClass() == BufferedInputStream.class && markpos == -1) {
|
||||||
int avail = count - pos;
|
int avail = count - pos;
|
||||||
if (avail > 0) {
|
if (avail > 0) {
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
package java.io;
|
package java.io;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import jdk.internal.misc.InternalLock;
|
|
||||||
import jdk.internal.misc.VM;
|
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_INITIAL_BUFFER_SIZE = 512;
|
||||||
private static final int DEFAULT_MAX_BUFFER_SIZE = 8192;
|
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.
|
* The internal buffer where data is stored.
|
||||||
*/
|
*/
|
||||||
|
@ -90,12 +86,9 @@ public class BufferedOutputStream extends FilterOutputStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getClass() == BufferedOutputStream.class) {
|
if (getClass() == BufferedOutputStream.class) {
|
||||||
// use InternalLock and resizable buffer when not sub-classed
|
// resizable when not sub-classed
|
||||||
this.lock = InternalLock.newLockOrNull();
|
this.buf = new byte[initialSize];
|
||||||
this.buf = new byte[initialSize]; // resizable
|
|
||||||
} else {
|
} else {
|
||||||
// use monitors and no resizing when sub-classed
|
|
||||||
this.lock = null;
|
|
||||||
this.buf = new byte[maxSize];
|
this.buf = new byte[maxSize];
|
||||||
}
|
}
|
||||||
this.maxBufSize = maxSize;
|
this.maxBufSize = maxSize;
|
||||||
|
@ -136,8 +129,6 @@ public class BufferedOutputStream extends FilterOutputStream {
|
||||||
* Grow buf to fit an additional len bytes if needed.
|
* Grow buf to fit an additional len bytes if needed.
|
||||||
* If possible, it grows by len+1 to avoid flushing when len bytes
|
* If possible, it grows by len+1 to avoid flushing when len bytes
|
||||||
* are added. A no-op if the buffer is not resizable.
|
* 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) {
|
private void growIfNeeded(int len) {
|
||||||
int neededSize = count + len + 1;
|
int neededSize = count + len + 1;
|
||||||
|
@ -157,22 +148,7 @@ public class BufferedOutputStream extends FilterOutputStream {
|
||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(int b) throws IOException {
|
public synchronized 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 {
|
|
||||||
growIfNeeded(1);
|
growIfNeeded(1);
|
||||||
if (count >= buf.length) {
|
if (count >= buf.length) {
|
||||||
flushBuffer();
|
flushBuffer();
|
||||||
|
@ -198,22 +174,7 @@ public class BufferedOutputStream extends FilterOutputStream {
|
||||||
* @throws IndexOutOfBoundsException {@inheritDoc}
|
* @throws IndexOutOfBoundsException {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(byte[] b, int off, int len) throws IOException {
|
public synchronized 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 {
|
|
||||||
if (len >= maxBufSize) {
|
if (len >= maxBufSize) {
|
||||||
/* If the request length exceeds the max size of the output buffer,
|
/* If the request length exceeds the max size of the output buffer,
|
||||||
flush the output buffer and then write the data directly.
|
flush the output buffer and then write the data directly.
|
||||||
|
@ -238,22 +199,7 @@ public class BufferedOutputStream extends FilterOutputStream {
|
||||||
* @see java.io.FilterOutputStream#out
|
* @see java.io.FilterOutputStream#out
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void flush() throws IOException {
|
public synchronized void flush() throws IOException {
|
||||||
if (lock != null) {
|
|
||||||
lock.lock();
|
|
||||||
try {
|
|
||||||
implFlush();
|
|
||||||
} finally {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (this) {
|
|
||||||
implFlush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void implFlush() throws IOException {
|
|
||||||
flushBuffer();
|
flushBuffer();
|
||||||
out.flush();
|
out.flush();
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@ import java.util.Spliterator;
|
||||||
import java.util.Spliterators;
|
import java.util.Spliterators;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import java.util.stream.StreamSupport;
|
import java.util.stream.StreamSupport;
|
||||||
import jdk.internal.misc.InternalLock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads text from a character-input stream, buffering characters so as to
|
* 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
|
* @throws IOException If an I/O error occurs
|
||||||
*/
|
*/
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
ensureOpen();
|
||||||
locker.lock();
|
for (;;) {
|
||||||
try {
|
if (nextChar >= nChars) {
|
||||||
return implRead();
|
fill();
|
||||||
} finally {
|
if (nextChar >= nChars)
|
||||||
locker.unlock();
|
return -1;
|
||||||
}
|
|
||||||
} 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;
|
|
||||||
}
|
}
|
||||||
|
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}
|
* @throws IOException {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public int read(char[] cbuf, int off, int len) throws IOException {
|
public int read(char[] cbuf, int off, int len) throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
ensureOpen();
|
||||||
locker.lock();
|
Objects.checkFromIndexSize(off, len, cbuf.length);
|
||||||
try {
|
if (len == 0) {
|
||||||
return implRead(cbuf, off, len);
|
return 0;
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
int n = read1(cbuf, off, len);
|
||||||
return implRead(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
|
* 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
|
* 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
|
* @throws IOException If an I/O error occurs
|
||||||
*/
|
*/
|
||||||
String readLine(boolean ignoreLF, boolean[] term) throws IOException {
|
String readLine(boolean ignoreLF, boolean[] term) throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
StringBuilder s = null;
|
||||||
locker.lock();
|
int startChar;
|
||||||
try {
|
|
||||||
return implReadLine(ignoreLF, term);
|
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
return implReadLine(ignoreLF, term);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String implReadLine(boolean ignoreLF, boolean[] term) throws IOException {
|
ensureOpen();
|
||||||
StringBuilder s = null;
|
boolean omitLF = ignoreLF || skipLF;
|
||||||
int startChar;
|
if (term != null) term[0] = false;
|
||||||
|
|
||||||
ensureOpen();
|
bufferLoop:
|
||||||
boolean omitLF = ignoreLF || skipLF;
|
for (;;) {
|
||||||
if (term != null) term[0] = false;
|
|
||||||
|
|
||||||
bufferLoop:
|
if (nextChar >= nChars)
|
||||||
for (;;) {
|
fill();
|
||||||
|
if (nextChar >= nChars) { /* EOF */
|
||||||
if (nextChar >= nChars)
|
if (s != null && s.length() > 0)
|
||||||
fill();
|
return s.toString();
|
||||||
if (nextChar >= nChars) { /* EOF */
|
else
|
||||||
if (s != null && s.length() > 0)
|
return null;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
boolean eol = false;
|
||||||
|
char c = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
startChar = nextChar;
|
/* Skip a leftover '\n', if necessary */
|
||||||
nextChar = i;
|
if (omitLF && (cb[nextChar] == '\n'))
|
||||||
|
nextChar++;
|
||||||
|
skipLF = false;
|
||||||
|
omitLF = false;
|
||||||
|
|
||||||
if (eol) {
|
charLoop:
|
||||||
String str;
|
for (i = nextChar; i < nChars; i++) {
|
||||||
if (s == null) {
|
c = cb[i];
|
||||||
str = new String(cb, startChar, i - startChar);
|
if ((c == '\n') || (c == '\r')) {
|
||||||
} else {
|
if (term != null) term[0] = true;
|
||||||
s.append(cb, startChar, i - startChar);
|
eol = true;
|
||||||
str = s.toString();
|
break charLoop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
nextChar++;
|
|
||||||
if (c == '\r') {
|
|
||||||
skipLF = true;
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s == null)
|
startChar = nextChar;
|
||||||
s = new StringBuilder(DEFAULT_EXPECTED_LINE_LENGTH);
|
nextChar = i;
|
||||||
s.append(cb, startChar, i - startChar);
|
|
||||||
|
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) {
|
if (n < 0L) {
|
||||||
throw new IllegalArgumentException("skip value is negative");
|
throw new IllegalArgumentException("skip value is negative");
|
||||||
}
|
}
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
ensureOpen();
|
||||||
locker.lock();
|
long r = n;
|
||||||
try {
|
while (r > 0) {
|
||||||
return implSkip(n);
|
if (nextChar >= nChars)
|
||||||
} finally {
|
fill();
|
||||||
locker.unlock();
|
if (nextChar >= nChars) /* EOF */
|
||||||
}
|
break;
|
||||||
} else {
|
if (skipLF) {
|
||||||
synchronized (lock) {
|
skipLF = false;
|
||||||
return implSkip(n);
|
if (cb[nextChar] == '\n') {
|
||||||
}
|
nextChar++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
long d = nChars - nextChar;
|
||||||
private long implSkip(long n) throws IOException {
|
if (r <= d) {
|
||||||
ensureOpen();
|
nextChar += (int)r;
|
||||||
long r = n;
|
r = 0;
|
||||||
while (r > 0) {
|
break;
|
||||||
if (nextChar >= nChars)
|
}
|
||||||
fill();
|
else {
|
||||||
if (nextChar >= nChars) /* EOF */
|
r -= d;
|
||||||
break;
|
nextChar = nChars;
|
||||||
if (skipLF) {
|
|
||||||
skipLF = false;
|
|
||||||
if (cb[nextChar] == '\n') {
|
|
||||||
nextChar++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
long d = nChars - nextChar;
|
return n - r;
|
||||||
if (r <= d) {
|
|
||||||
nextChar += (int)r;
|
|
||||||
r = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
r -= d;
|
|
||||||
nextChar = nChars;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return n - r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -501,42 +444,28 @@ public class BufferedReader extends Reader {
|
||||||
* @throws IOException If an I/O error occurs
|
* @throws IOException If an I/O error occurs
|
||||||
*/
|
*/
|
||||||
public boolean ready() throws IOException {
|
public boolean ready() throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
ensureOpen();
|
||||||
locker.lock();
|
|
||||||
try {
|
|
||||||
return implReady();
|
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
return implReady();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 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 (nextChar >= nChars && in.ready()) {
|
if (skipLF) {
|
||||||
fill();
|
/* Note that in.ready() will return true if and only if the next
|
||||||
}
|
* read on the stream will not block.
|
||||||
if (nextChar < nChars) {
|
*/
|
||||||
if (cb[nextChar] == '\n')
|
if (nextChar >= nChars && in.ready()) {
|
||||||
nextChar++;
|
fill();
|
||||||
skipLF = false;
|
}
|
||||||
|
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) {
|
if (readAheadLimit < 0) {
|
||||||
throw new IllegalArgumentException("Read-ahead limit < 0");
|
throw new IllegalArgumentException("Read-ahead limit < 0");
|
||||||
}
|
}
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
ensureOpen();
|
||||||
locker.lock();
|
this.readAheadLimit = readAheadLimit;
|
||||||
try {
|
markedChar = nextChar;
|
||||||
implMark(readAheadLimit);
|
markedSkipLF = skipLF;
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
implMark(readAheadLimit);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void implMark(int readAheadLimit) throws IOException {
|
|
||||||
ensureOpen();
|
|
||||||
this.readAheadLimit = readAheadLimit;
|
|
||||||
markedChar = nextChar;
|
|
||||||
markedSkipLF = skipLF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the stream to the most recent mark.
|
* Resets the stream to the most recent mark.
|
||||||
*
|
*
|
||||||
|
@ -595,55 +510,27 @@ public class BufferedReader extends Reader {
|
||||||
* or if the mark has been invalidated
|
* or if the mark has been invalidated
|
||||||
*/
|
*/
|
||||||
public void reset() throws IOException {
|
public void reset() throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
ensureOpen();
|
||||||
locker.lock();
|
if (markedChar < 0)
|
||||||
try {
|
throw new IOException((markedChar == INVALIDATED)
|
||||||
implReset();
|
? "Mark invalid"
|
||||||
} finally {
|
: "Stream not marked");
|
||||||
locker.unlock();
|
nextChar = markedChar;
|
||||||
}
|
skipLF = markedSkipLF;
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
implReset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
public void close() throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
if (in == null)
|
||||||
locker.lock();
|
return;
|
||||||
try {
|
try {
|
||||||
implClose();
|
in.close();
|
||||||
} finally {
|
} 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.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import jdk.internal.misc.InternalLock;
|
|
||||||
import jdk.internal.misc.VM;
|
import jdk.internal.misc.VM;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -162,58 +161,30 @@ public class BufferedWriter extends Writer {
|
||||||
* may be invoked by PrintStream.
|
* may be invoked by PrintStream.
|
||||||
*/
|
*/
|
||||||
void flushBuffer() throws IOException {
|
void flushBuffer() throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
ensureOpen();
|
||||||
locker.lock();
|
if (nextChar == 0)
|
||||||
try {
|
return;
|
||||||
implFlushBuffer();
|
out.write(cb, 0, nextChar);
|
||||||
} finally {
|
nextChar = 0;
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
implFlushBuffer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void implFlushBuffer() throws IOException {
|
|
||||||
ensureOpen();
|
|
||||||
if (nextChar == 0)
|
|
||||||
return;
|
|
||||||
out.write(cb, 0, nextChar);
|
|
||||||
nextChar = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes a single character.
|
* Writes a single character.
|
||||||
*
|
*
|
||||||
* @throws IOException If an I/O error occurs
|
* @throws IOException If an I/O error occurs
|
||||||
*/
|
*/
|
||||||
public void write(int c) throws IOException {
|
public void write(int c) throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
ensureOpen();
|
||||||
locker.lock();
|
growIfNeeded(1);
|
||||||
try {
|
if (nextChar >= nChars)
|
||||||
implWrite(c);
|
flushBuffer();
|
||||||
} finally {
|
cb[nextChar++] = (char) c;
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
implWrite(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
|
* 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.
|
* 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
|
* @throws IOException If an I/O error occurs
|
||||||
*/
|
*/
|
||||||
public void write(char[] cbuf, int off, int len) throws IOException {
|
public void write(char[] cbuf, int off, int len) throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
ensureOpen();
|
||||||
locker.lock();
|
Objects.checkFromIndexSize(off, len, cbuf.length);
|
||||||
try {
|
if (len == 0) {
|
||||||
implWrite(cbuf, off, len);
|
return;
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
implWrite(cbuf, off, len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void implWrite(char[] cbuf, int off, int len) throws IOException {
|
if (len >= maxChars) {
|
||||||
ensureOpen();
|
/* If the request length exceeds the max size of the output buffer,
|
||||||
Objects.checkFromIndexSize(off, len, cbuf.length);
|
flush the buffer and then write the data directly. In this
|
||||||
if (len == 0) {
|
way buffered streams will cascade harmlessly. */
|
||||||
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) {
|
|
||||||
flushBuffer();
|
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
|
* @throws IOException If an I/O error occurs
|
||||||
*/
|
*/
|
||||||
public void write(String s, int off, int len) throws IOException {
|
public void write(String s, int off, int len) throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
ensureOpen();
|
||||||
locker.lock();
|
growIfNeeded(len);
|
||||||
try {
|
int b = off, t = off + len;
|
||||||
implWrite(s, off, len);
|
while (b < t) {
|
||||||
} finally {
|
int d = min(nChars - nextChar, t - b);
|
||||||
locker.unlock();
|
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
|
* @throws IOException If an I/O error occurs
|
||||||
*/
|
*/
|
||||||
public void flush() throws IOException {
|
public void flush() throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
flushBuffer();
|
||||||
locker.lock();
|
out.flush();
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("try")
|
@SuppressWarnings("try")
|
||||||
private void implClose() throws IOException {
|
public void close() throws IOException {
|
||||||
if (out == null) {
|
synchronized (lock) {
|
||||||
return;
|
if (out == null) {
|
||||||
}
|
return;
|
||||||
try (Writer w = out) {
|
}
|
||||||
flushBuffer();
|
try (Writer w = out) {
|
||||||
} finally {
|
flushBuffer();
|
||||||
out = null;
|
} finally {
|
||||||
cb = null;
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.CharBuffer;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.CharsetDecoder;
|
import java.nio.charset.CharsetDecoder;
|
||||||
import jdk.internal.misc.InternalLock;
|
|
||||||
import sun.nio.cs.StreamDecoder;
|
import sun.nio.cs.StreamDecoder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,20 +61,6 @@ import sun.nio.cs.StreamDecoder;
|
||||||
public class InputStreamReader extends Reader {
|
public class InputStreamReader extends Reader {
|
||||||
private final StreamDecoder sd;
|
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
|
* Creates an InputStreamReader that uses the
|
||||||
* {@link Charset#defaultCharset() default charset}.
|
* {@link Charset#defaultCharset() default charset}.
|
||||||
|
@ -88,7 +73,7 @@ public class InputStreamReader extends Reader {
|
||||||
public InputStreamReader(InputStream in) {
|
public InputStreamReader(InputStream in) {
|
||||||
super(in);
|
super(in);
|
||||||
Charset cs = Charset.defaultCharset();
|
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);
|
super(in);
|
||||||
if (charsetName == null)
|
if (charsetName == null)
|
||||||
throw new NullPointerException("charsetName");
|
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);
|
super(in);
|
||||||
if (cs == null)
|
if (cs == null)
|
||||||
throw new NullPointerException("charset");
|
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);
|
super(in);
|
||||||
if (dec == null)
|
if (dec == null)
|
||||||
throw new NullPointerException("charset decoder");
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.CharBuffer;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.CharsetEncoder;
|
import java.nio.charset.CharsetEncoder;
|
||||||
import jdk.internal.misc.InternalLock;
|
|
||||||
import sun.nio.cs.StreamEncoder;
|
import sun.nio.cs.StreamEncoder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,20 +74,6 @@ import sun.nio.cs.StreamEncoder;
|
||||||
public class OutputStreamWriter extends Writer {
|
public class OutputStreamWriter extends Writer {
|
||||||
private final StreamEncoder se;
|
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.
|
* Creates an OutputStreamWriter that uses the named charset.
|
||||||
*
|
*
|
||||||
|
@ -108,7 +93,7 @@ public class OutputStreamWriter extends Writer {
|
||||||
super(out);
|
super(out);
|
||||||
if (charsetName == null)
|
if (charsetName == null)
|
||||||
throw new NullPointerException("charsetName");
|
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")
|
@SuppressWarnings("this-escape")
|
||||||
public OutputStreamWriter(OutputStream out) {
|
public OutputStreamWriter(OutputStream out) {
|
||||||
super(out);
|
super(out);
|
||||||
se = StreamEncoder.forOutputStreamWriter(out, lockFor(this),
|
se = StreamEncoder.forOutputStreamWriter(out, this,
|
||||||
out instanceof PrintStream ps ? ps.charset() : Charset.defaultCharset());
|
out instanceof PrintStream ps ? ps.charset() : Charset.defaultCharset());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +127,7 @@ public class OutputStreamWriter extends Writer {
|
||||||
super(out);
|
super(out);
|
||||||
if (cs == null)
|
if (cs == null)
|
||||||
throw new NullPointerException("charset");
|
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);
|
super(out);
|
||||||
if (enc == null)
|
if (enc == null)
|
||||||
throw new NullPointerException("charset encoder");
|
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.Charset;
|
||||||
import java.nio.charset.IllegalCharsetNameException;
|
import java.nio.charset.IllegalCharsetNameException;
|
||||||
import java.nio.charset.UnsupportedCharsetException;
|
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,
|
* A {@code PrintStream} adds functionality to another output stream,
|
||||||
|
@ -67,9 +64,6 @@ import jdk.internal.misc.InternalLock;
|
||||||
public class PrintStream extends FilterOutputStream
|
public class PrintStream extends FilterOutputStream
|
||||||
implements Appendable, Closeable
|
implements Appendable, Closeable
|
||||||
{
|
{
|
||||||
// initialized to null when PrintStream is sub-classed
|
|
||||||
private final InternalLock lock;
|
|
||||||
|
|
||||||
private final boolean autoFlush;
|
private final boolean autoFlush;
|
||||||
private boolean trouble = false;
|
private boolean trouble = false;
|
||||||
private Formatter formatter;
|
private Formatter formatter;
|
||||||
|
@ -117,13 +111,6 @@ public class PrintStream extends FilterOutputStream
|
||||||
this.charset = out instanceof PrintStream ps ? ps.charset() : Charset.defaultCharset();
|
this.charset = out instanceof PrintStream ps ? ps.charset() : Charset.defaultCharset();
|
||||||
this.charOut = new OutputStreamWriter(this, charset);
|
this.charOut = new OutputStreamWriter(this, charset);
|
||||||
this.textOut = new BufferedWriter(charOut);
|
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
|
/* 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.charOut = new OutputStreamWriter(this, charset);
|
||||||
this.textOut = new BufferedWriter(charOut);
|
this.textOut = new BufferedWriter(charOut);
|
||||||
this.charset = charset;
|
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
|
@Override
|
||||||
public void flush() {
|
public void flush() {
|
||||||
if (lock != null) {
|
synchronized (this) {
|
||||||
lock.lock();
|
|
||||||
try {
|
try {
|
||||||
implFlush();
|
ensureOpen();
|
||||||
} finally {
|
out.flush();
|
||||||
lock.unlock();
|
|
||||||
}
|
}
|
||||||
} else {
|
catch (IOException x) {
|
||||||
synchronized (this) {
|
trouble = true;
|
||||||
implFlush();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void implFlush() {
|
|
||||||
try {
|
|
||||||
ensureOpen();
|
|
||||||
out.flush();
|
|
||||||
}
|
|
||||||
catch (IOException x) {
|
|
||||||
trouble = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean closing = false; /* To avoid recursive closing */
|
private boolean closing = false; /* To avoid recursive closing */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -454,33 +421,20 @@ public class PrintStream extends FilterOutputStream
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
if (lock != null) {
|
synchronized (this) {
|
||||||
lock.lock();
|
if (!closing) {
|
||||||
try {
|
closing = true;
|
||||||
implClose();
|
try {
|
||||||
} finally {
|
textOut.close();
|
||||||
lock.unlock();
|
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
|
@Override
|
||||||
public void write(int b) {
|
public void write(int b) {
|
||||||
try {
|
try {
|
||||||
if (lock != null) {
|
synchronized (this) {
|
||||||
lock.lock();
|
ensureOpen();
|
||||||
try {
|
out.write(b);
|
||||||
implWrite(b);
|
if ((b == '\n') && autoFlush)
|
||||||
} finally {
|
out.flush();
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (this) {
|
|
||||||
implWrite(b);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InterruptedIOException x) {
|
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
|
* Writes {@code len} bytes from the specified byte array starting at
|
||||||
* offset {@code off} to this stream. If automatic flushing is
|
* offset {@code off} to this stream. If automatic flushing is
|
||||||
|
@ -593,17 +534,11 @@ public class PrintStream extends FilterOutputStream
|
||||||
@Override
|
@Override
|
||||||
public void write(byte[] buf, int off, int len) {
|
public void write(byte[] buf, int off, int len) {
|
||||||
try {
|
try {
|
||||||
if (lock != null) {
|
synchronized (this) {
|
||||||
lock.lock();
|
ensureOpen();
|
||||||
try {
|
out.write(buf, off, len);
|
||||||
implWrite(buf, off, len);
|
if (autoFlush)
|
||||||
} finally {
|
out.flush();
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (this) {
|
|
||||||
implWrite(buf, off, len);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InterruptedIOException x) {
|
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
|
* Writes all bytes from the specified byte array to this stream. If
|
||||||
* automatic flushing is enabled then the {@code flush} method will be
|
* 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) {
|
private void write(char[] buf) {
|
||||||
try {
|
try {
|
||||||
if (lock != null) {
|
synchronized (this) {
|
||||||
lock.lock();
|
ensureOpen();
|
||||||
try {
|
textOut.write(buf);
|
||||||
implWrite(buf);
|
textOut.flushBuffer();
|
||||||
} finally {
|
charOut.flushBuffer();
|
||||||
lock.unlock();
|
if (autoFlush) {
|
||||||
}
|
for (int i = 0; i < buf.length; i++)
|
||||||
} else {
|
if (buf[i] == '\n') {
|
||||||
synchronized (this) {
|
out.flush();
|
||||||
implWrite(buf);
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (InterruptedIOException x) {
|
} 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
|
// Used to optimize away back-to-back flushing and synchronization when
|
||||||
// using println, but since subclasses could exist which depend on
|
// using println, but since subclasses could exist which depend on
|
||||||
// observing a call to print followed by newLine() we only use this if
|
// observing a call to print followed by newLine() we only use this if
|
||||||
// getClass() == PrintStream.class to avoid compatibility issues.
|
// getClass() == PrintStream.class to avoid compatibility issues.
|
||||||
private void writeln(char[] buf) {
|
private void writeln(char[] buf) {
|
||||||
try {
|
try {
|
||||||
if (lock != null) {
|
synchronized (this) {
|
||||||
lock.lock();
|
ensureOpen();
|
||||||
try {
|
textOut.write(buf);
|
||||||
implWriteln(buf);
|
textOut.newLine();
|
||||||
} finally {
|
textOut.flushBuffer();
|
||||||
lock.unlock();
|
charOut.flushBuffer();
|
||||||
}
|
if (autoFlush)
|
||||||
} else {
|
out.flush();
|
||||||
synchronized (this) {
|
|
||||||
implWriteln(buf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InterruptedIOException x) {
|
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) {
|
private void write(String s) {
|
||||||
try {
|
try {
|
||||||
if (lock != null) {
|
synchronized (this) {
|
||||||
lock.lock();
|
ensureOpen();
|
||||||
try {
|
textOut.write(s);
|
||||||
implWrite(s);
|
textOut.flushBuffer();
|
||||||
} finally {
|
charOut.flushBuffer();
|
||||||
lock.unlock();
|
if (autoFlush && (s.indexOf('\n') >= 0))
|
||||||
}
|
out.flush();
|
||||||
} else {
|
|
||||||
synchronized (this) {
|
|
||||||
implWrite(s);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InterruptedIOException x) {
|
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
|
// Used to optimize away back-to-back flushing and synchronization when
|
||||||
// using println, but since subclasses could exist which depend on
|
// using println, but since subclasses could exist which depend on
|
||||||
// observing a call to print followed by newLine we only use this if
|
// observing a call to print followed by newLine we only use this if
|
||||||
// getClass() == PrintStream.class to avoid compatibility issues.
|
// getClass() == PrintStream.class to avoid compatibility issues.
|
||||||
private void writeln(String s) {
|
private void writeln(String s) {
|
||||||
try {
|
try {
|
||||||
if (lock != null) {
|
synchronized (this) {
|
||||||
lock.lock();
|
ensureOpen();
|
||||||
try {
|
textOut.write(s);
|
||||||
implWriteln(s);
|
textOut.newLine();
|
||||||
} finally {
|
textOut.flushBuffer();
|
||||||
lock.unlock();
|
charOut.flushBuffer();
|
||||||
}
|
if (autoFlush)
|
||||||
} else {
|
out.flush();
|
||||||
synchronized (this) {
|
|
||||||
implWriteln(s);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InterruptedIOException x) {
|
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() {
|
private void newLine() {
|
||||||
try {
|
try {
|
||||||
if (lock != null) {
|
synchronized (this) {
|
||||||
lock.lock();
|
ensureOpen();
|
||||||
try {
|
textOut.newLine();
|
||||||
implNewLine();
|
textOut.flushBuffer();
|
||||||
} finally {
|
charOut.flushBuffer();
|
||||||
lock.unlock();
|
if (autoFlush)
|
||||||
}
|
out.flush();
|
||||||
} else {
|
|
||||||
synchronized (this) {
|
|
||||||
implNewLine();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InterruptedIOException x) {
|
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 */
|
/* Methods that do not terminate lines */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1314,17 +1176,11 @@ public class PrintStream extends FilterOutputStream
|
||||||
*/
|
*/
|
||||||
public PrintStream format(String format, Object ... args) {
|
public PrintStream format(String format, Object ... args) {
|
||||||
try {
|
try {
|
||||||
if (lock != null) {
|
synchronized (this) {
|
||||||
lock.lock();
|
ensureOpen();
|
||||||
try {
|
if ((formatter == null) || (formatter.locale() != Locale.getDefault(Locale.Category.FORMAT)))
|
||||||
implFormat(format, args);
|
formatter = new Formatter((Appendable) this);
|
||||||
} finally {
|
formatter.format(Locale.getDefault(Locale.Category.FORMAT), format, args);
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (this) {
|
|
||||||
implFormat(format, args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (InterruptedIOException x) {
|
} catch (InterruptedIOException x) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
|
@ -1334,13 +1190,6 @@ public class PrintStream extends FilterOutputStream
|
||||||
return this;
|
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
|
* Writes a formatted string to this output stream using the specified
|
||||||
* format string and arguments.
|
* format string and arguments.
|
||||||
|
@ -1383,17 +1232,11 @@ public class PrintStream extends FilterOutputStream
|
||||||
*/
|
*/
|
||||||
public PrintStream format(Locale l, String format, Object ... args) {
|
public PrintStream format(Locale l, String format, Object ... args) {
|
||||||
try {
|
try {
|
||||||
if (lock != null) {
|
synchronized (this) {
|
||||||
lock.lock();
|
ensureOpen();
|
||||||
try {
|
if ((formatter == null) || (formatter.locale() != l))
|
||||||
implFormat(l, format, args);
|
formatter = new Formatter(this, l);
|
||||||
} finally {
|
formatter.format(l, format, args);
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (this) {
|
|
||||||
implFormat(l, format, args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (InterruptedIOException x) {
|
} catch (InterruptedIOException x) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
|
@ -1403,13 +1246,6 @@ public class PrintStream extends FilterOutputStream
|
||||||
return this;
|
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.
|
* Appends the specified character sequence to this output stream.
|
||||||
*
|
*
|
||||||
|
@ -1511,13 +1347,4 @@ public class PrintStream extends FilterOutputStream
|
||||||
public Charset charset() {
|
public Charset charset() {
|
||||||
return 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.Charset;
|
||||||
import java.nio.charset.IllegalCharsetNameException;
|
import java.nio.charset.IllegalCharsetNameException;
|
||||||
import java.nio.charset.UnsupportedCharsetException;
|
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
|
* Prints formatted representations of objects to a text-output stream. This
|
||||||
|
@ -377,27 +374,13 @@ public class PrintWriter extends Writer {
|
||||||
* @see #checkError()
|
* @see #checkError()
|
||||||
*/
|
*/
|
||||||
public void flush() {
|
public void flush() {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
|
||||||
locker.lock();
|
|
||||||
try {
|
try {
|
||||||
implFlush();
|
ensureOpen();
|
||||||
} finally {
|
out.flush();
|
||||||
locker.unlock();
|
} 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()
|
* @see #checkError()
|
||||||
*/
|
*/
|
||||||
public void close() {
|
public void close() {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
|
||||||
locker.lock();
|
|
||||||
try {
|
try {
|
||||||
implClose();
|
if (out != null) {
|
||||||
} finally {
|
out.close();
|
||||||
locker.unlock();
|
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.
|
* @param c int specifying a character to be written.
|
||||||
*/
|
*/
|
||||||
public void write(int c) {
|
public void write(int c) {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
|
||||||
locker.lock();
|
|
||||||
try {
|
try {
|
||||||
implWrite(c);
|
ensureOpen();
|
||||||
} finally {
|
out.write(c);
|
||||||
locker.unlock();
|
} 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}
|
* to throw an {@code IndexOutOfBoundsException}
|
||||||
*/
|
*/
|
||||||
public void write(char[] buf, int off, int len) {
|
public void write(char[] buf, int off, int len) {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
|
||||||
locker.lock();
|
|
||||||
try {
|
try {
|
||||||
implWrite(buf, off, len);
|
ensureOpen();
|
||||||
} finally {
|
out.write(buf, off, len);
|
||||||
locker.unlock();
|
} 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}
|
* to throw an {@code IndexOutOfBoundsException}
|
||||||
*/
|
*/
|
||||||
public void write(String s, int off, int len) {
|
public void write(String s, int off, int len) {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
|
||||||
locker.lock();
|
|
||||||
try {
|
try {
|
||||||
implWrite(s, off, len);
|
ensureOpen();
|
||||||
} finally {
|
out.write(s, off, len);
|
||||||
locker.unlock();
|
} 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() {
|
private void newLine() {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
|
||||||
locker.lock();
|
|
||||||
try {
|
try {
|
||||||
implNewLine();
|
ensureOpen();
|
||||||
} finally {
|
out.write(System.lineSeparator());
|
||||||
locker.unlock();
|
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
|
* @param x the {@code boolean} value to be printed
|
||||||
*/
|
*/
|
||||||
public void println(boolean x) {
|
public void println(boolean x) {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
print(x);
|
||||||
locker.lock();
|
println();
|
||||||
try {
|
|
||||||
print(x);
|
|
||||||
println();
|
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
print(x);
|
|
||||||
println();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -813,20 +715,9 @@ public class PrintWriter extends Writer {
|
||||||
* @param x the {@code char} value to be printed
|
* @param x the {@code char} value to be printed
|
||||||
*/
|
*/
|
||||||
public void println(char x) {
|
public void println(char x) {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
print(x);
|
||||||
locker.lock();
|
println();
|
||||||
try {
|
|
||||||
print(x);
|
|
||||||
println();
|
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
print(x);
|
|
||||||
println();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -838,20 +729,9 @@ public class PrintWriter extends Writer {
|
||||||
* @param x the {@code int} value to be printed
|
* @param x the {@code int} value to be printed
|
||||||
*/
|
*/
|
||||||
public void println(int x) {
|
public void println(int x) {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
print(x);
|
||||||
locker.lock();
|
println();
|
||||||
try {
|
|
||||||
print(x);
|
|
||||||
println();
|
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
print(x);
|
|
||||||
println();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -863,20 +743,9 @@ public class PrintWriter extends Writer {
|
||||||
* @param x the {@code long} value to be printed
|
* @param x the {@code long} value to be printed
|
||||||
*/
|
*/
|
||||||
public void println(long x) {
|
public void println(long x) {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
print(x);
|
||||||
locker.lock();
|
println();
|
||||||
try {
|
|
||||||
print(x);
|
|
||||||
println();
|
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
print(x);
|
|
||||||
println();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,20 +757,9 @@ public class PrintWriter extends Writer {
|
||||||
* @param x the {@code float} value to be printed
|
* @param x the {@code float} value to be printed
|
||||||
*/
|
*/
|
||||||
public void println(float x) {
|
public void println(float x) {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
print(x);
|
||||||
locker.lock();
|
println();
|
||||||
try {
|
|
||||||
print(x);
|
|
||||||
println();
|
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
print(x);
|
|
||||||
println();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -913,20 +771,9 @@ public class PrintWriter extends Writer {
|
||||||
* @param x the {@code double} value to be printed
|
* @param x the {@code double} value to be printed
|
||||||
*/
|
*/
|
||||||
public void println(double x) {
|
public void println(double x) {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
print(x);
|
||||||
locker.lock();
|
println();
|
||||||
try {
|
|
||||||
print(x);
|
|
||||||
println();
|
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
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
|
* @param x the array of {@code char} values to be printed
|
||||||
*/
|
*/
|
||||||
public void println(char[] x) {
|
public void println(char[] x) {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
print(x);
|
||||||
locker.lock();
|
println();
|
||||||
try {
|
|
||||||
print(x);
|
|
||||||
println();
|
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
print(x);
|
|
||||||
println();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -963,20 +799,9 @@ public class PrintWriter extends Writer {
|
||||||
* @param x the {@code String} value to be printed
|
* @param x the {@code String} value to be printed
|
||||||
*/
|
*/
|
||||||
public void println(String x) {
|
public void println(String x) {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
print(x);
|
||||||
locker.lock();
|
println();
|
||||||
try {
|
|
||||||
print(x);
|
|
||||||
println();
|
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
print(x);
|
|
||||||
println();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -991,20 +816,9 @@ public class PrintWriter extends Writer {
|
||||||
*/
|
*/
|
||||||
public void println(Object x) {
|
public void println(Object x) {
|
||||||
String s = String.valueOf(x);
|
String s = String.valueOf(x);
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
print(s);
|
||||||
locker.lock();
|
println();
|
||||||
try {
|
|
||||||
print(s);
|
|
||||||
println();
|
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
print(s);
|
|
||||||
println();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1150,38 +964,24 @@ public class PrintWriter extends Writer {
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
public PrintWriter format(String format, Object ... args) {
|
public PrintWriter format(String format, Object ... args) {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
|
||||||
locker.lock();
|
|
||||||
try {
|
try {
|
||||||
implFormat(format, args);
|
ensureOpen();
|
||||||
} finally {
|
if ((formatter == null)
|
||||||
locker.unlock();
|
|| (formatter.locale() != Locale.getDefault()))
|
||||||
}
|
formatter = new Formatter(this);
|
||||||
} else {
|
formatter.format(Locale.getDefault(), format, args);
|
||||||
synchronized (lock) {
|
if (autoFlush)
|
||||||
implFormat(format, args);
|
out.flush();
|
||||||
|
} catch (InterruptedIOException x) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
} catch (IOException x) {
|
||||||
|
trouble = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this;
|
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
|
* Writes a formatted string to this writer using the specified format
|
||||||
* string and arguments. If automatic flushing is enabled, calls to this
|
* string and arguments. If automatic flushing is enabled, calls to this
|
||||||
|
@ -1224,37 +1024,23 @@ public class PrintWriter extends Writer {
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
public PrintWriter format(Locale l, String format, Object ... args) {
|
public PrintWriter format(Locale l, String format, Object ... args) {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
|
||||||
locker.lock();
|
|
||||||
try {
|
try {
|
||||||
implFormat(l, format, args);
|
ensureOpen();
|
||||||
} finally {
|
if ((formatter == null) || (formatter.locale() != l))
|
||||||
locker.unlock();
|
formatter = new Formatter(this, l);
|
||||||
}
|
formatter.format(l, format, args);
|
||||||
} else {
|
if (autoFlush)
|
||||||
synchronized (lock) {
|
out.flush();
|
||||||
implFormat(l, format, args);
|
} catch (InterruptedIOException x) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
} catch (IOException x) {
|
||||||
|
trouble = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this;
|
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.
|
* Appends the specified character sequence to this writer.
|
||||||
*
|
*
|
||||||
|
@ -1346,12 +1132,4 @@ public class PrintWriter extends Writer {
|
||||||
write(c);
|
write(c);
|
||||||
return this;
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import jdk.internal.misc.InternalLock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@code PushbackInputStream} adds
|
* A {@code PushbackInputStream} adds
|
||||||
|
@ -54,10 +53,6 @@ import jdk.internal.misc.InternalLock;
|
||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
public class PushbackInputStream extends FilterInputStream {
|
public class PushbackInputStream extends FilterInputStream {
|
||||||
|
|
||||||
// initialized to null when PushbackInputStream is sub-classed
|
|
||||||
private final InternalLock closeLock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The pushback buffer.
|
* The pushback buffer.
|
||||||
* @since 1.1
|
* @since 1.1
|
||||||
|
@ -101,13 +96,6 @@ public class PushbackInputStream extends FilterInputStream {
|
||||||
}
|
}
|
||||||
this.buf = new byte[size];
|
this.buf = new byte[size];
|
||||||
this.pos = 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.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
public void close() throws IOException {
|
public synchronized void close() throws IOException {
|
||||||
if (closeLock != null) {
|
if (in == null)
|
||||||
closeLock.lock();
|
return;
|
||||||
try {
|
in.close();
|
||||||
implClose();
|
in = null;
|
||||||
} finally {
|
buf = null;
|
||||||
closeLock.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (this) {
|
|
||||||
implClose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void implClose() throws IOException {
|
|
||||||
if (in != null) {
|
|
||||||
in.close();
|
|
||||||
in = null;
|
|
||||||
buf = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -28,7 +28,6 @@ package java.io;
|
||||||
import java.nio.CharBuffer;
|
import java.nio.CharBuffer;
|
||||||
import java.nio.ReadOnlyBufferException;
|
import java.nio.ReadOnlyBufferException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import jdk.internal.misc.InternalLock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class for reading character streams. The only methods that a
|
* 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;
|
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.
|
* Attempts to read characters into the specified character buffer.
|
||||||
* The buffer is used as a repository of characters as-is: the only
|
* 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 {
|
public long skip(long n) throws IOException {
|
||||||
if (n < 0L)
|
if (n < 0L)
|
||||||
throw new IllegalArgumentException("skip value is negative");
|
throw new IllegalArgumentException("skip value is negative");
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
int nn = (int) Math.min(n, maxSkipBufferSize);
|
||||||
locker.lock();
|
if ((skipBuffer == null) || (skipBuffer.length < nn))
|
||||||
try {
|
skipBuffer = new char[nn];
|
||||||
return implSkip(n);
|
long r = n;
|
||||||
} finally {
|
while (r > 0) {
|
||||||
locker.unlock();
|
int nc = read(skipBuffer, 0, (int)Math.min(r, nn));
|
||||||
}
|
if (nc == -1)
|
||||||
} else {
|
break;
|
||||||
synchronized (lock) {
|
r -= nc;
|
||||||
return implSkip(n);
|
|
||||||
}
|
}
|
||||||
|
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.
|
* Tells whether this stream is ready to be read.
|
||||||
*
|
*
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
package java.io;
|
package java.io;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import jdk.internal.misc.InternalLock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class for writing to character streams. The only methods that a
|
* 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;
|
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
|
* Creates a new character-stream writer whose critical sections will
|
||||||
* synchronize on the given object.
|
* synchronize on the given object.
|
||||||
|
@ -206,29 +190,15 @@ public abstract class Writer implements Appendable, Closeable, Flushable {
|
||||||
* If an I/O error occurs
|
* If an I/O error occurs
|
||||||
*/
|
*/
|
||||||
public void write(int c) throws IOException {
|
public void write(int c) throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
if (writeBuffer == null){
|
||||||
locker.lock();
|
writeBuffer = new char[WRITE_BUFFER_SIZE];
|
||||||
try {
|
|
||||||
implWrite(c);
|
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
implWrite(c);
|
|
||||||
}
|
}
|
||||||
|
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.
|
* Writes an array of characters.
|
||||||
*
|
*
|
||||||
|
@ -305,35 +275,21 @@ public abstract class Writer implements Appendable, Closeable, Flushable {
|
||||||
* If an I/O error occurs
|
* If an I/O error occurs
|
||||||
*/
|
*/
|
||||||
public void write(String str, int off, int len) throws IOException {
|
public void write(String str, int off, int len) throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
char cbuf[];
|
||||||
locker.lock();
|
if (len <= WRITE_BUFFER_SIZE) {
|
||||||
try {
|
if (writeBuffer == null) {
|
||||||
implWrite(str, off, len);
|
writeBuffer = new char[WRITE_BUFFER_SIZE];
|
||||||
} finally {
|
}
|
||||||
locker.unlock();
|
cbuf = writeBuffer;
|
||||||
}
|
} else { // Don't permanently allocate very large buffers.
|
||||||
} else {
|
cbuf = new char[len];
|
||||||
synchronized (lock) {
|
|
||||||
implWrite(str, off, 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.
|
* 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import jdk.internal.access.SharedSecrets;
|
|
||||||
import jdk.internal.event.ThrowableTracer;
|
import jdk.internal.event.ThrowableTracer;
|
||||||
import jdk.internal.misc.InternalLock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@code Throwable} class is the superclass of all errors and
|
* 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) {
|
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
|
// Guard against malicious overrides of Throwable.equals by
|
||||||
// using a Set with identity equality semantics.
|
// using a Set with identity equality semantics.
|
||||||
Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<>());
|
Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<>());
|
||||||
dejaVu.add(this);
|
dejaVu.add(this);
|
||||||
|
|
||||||
// Print our stack trace
|
synchronized(s.lock()) {
|
||||||
s.println(this);
|
// Print our stack trace
|
||||||
StackTraceElement[] trace = getOurStackTrace();
|
s.println(this);
|
||||||
for (StackTraceElement traceElement : trace)
|
StackTraceElement[] trace = getOurStackTrace();
|
||||||
s.println("\tat " + traceElement);
|
for (StackTraceElement traceElement : trace)
|
||||||
|
s.println("\tat " + traceElement);
|
||||||
|
|
||||||
// Print suppressed exceptions, if any
|
// Print suppressed exceptions, if any
|
||||||
for (Throwable se : getSuppressed())
|
for (Throwable se : getSuppressed())
|
||||||
se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
|
se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
|
||||||
|
|
||||||
// Print cause, if any
|
// Print cause, if any
|
||||||
Throwable ourCause = getCause();
|
Throwable ourCause = getCause();
|
||||||
if (ourCause != null)
|
if (ourCause != null)
|
||||||
ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
|
ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -733,7 +719,7 @@ public class Throwable implements Serializable {
|
||||||
String caption,
|
String caption,
|
||||||
String prefix,
|
String prefix,
|
||||||
Set<Throwable> dejaVu) {
|
Set<Throwable> dejaVu) {
|
||||||
assert s.isLockedByCurrentThread();
|
assert Thread.holdsLock(s.lock());
|
||||||
if (dejaVu.contains(this)) {
|
if (dejaVu.contains(this)) {
|
||||||
s.println(prefix + caption + "[CIRCULAR REFERENCE: " + this + "]");
|
s.println(prefix + caption + "[CIRCULAR REFERENCE: " + this + "]");
|
||||||
} else {
|
} else {
|
||||||
|
@ -785,15 +771,6 @@ public class Throwable implements Serializable {
|
||||||
/** Returns the object to be locked when using this StreamOrWriter */
|
/** Returns the object to be locked when using this StreamOrWriter */
|
||||||
abstract Object lock();
|
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 */
|
/** Prints the specified string as a line on this StreamOrWriter */
|
||||||
abstract void println(Object o);
|
abstract void println(Object o);
|
||||||
}
|
}
|
||||||
|
@ -806,7 +783,7 @@ public class Throwable implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
Object lock() {
|
Object lock() {
|
||||||
return SharedSecrets.getJavaIOPrintStreamAccess().lock(printStream);
|
return printStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
void println(Object o) {
|
void println(Object o) {
|
||||||
|
@ -822,7 +799,7 @@ public class Throwable implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
Object lock() {
|
Object lock() {
|
||||||
return SharedSecrets.getJavaIOPrintWriterAccess().lock(printWriter);
|
return printWriter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void println(Object o) {
|
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 JavaLangRefAccess javaLangRefAccess;
|
||||||
private static JavaLangReflectAccess javaLangReflectAccess;
|
private static JavaLangReflectAccess javaLangReflectAccess;
|
||||||
private static JavaIOAccess javaIOAccess;
|
private static JavaIOAccess javaIOAccess;
|
||||||
private static JavaIOPrintStreamAccess javaIOPrintStreamAccess;
|
|
||||||
private static JavaIOPrintWriterAccess javaIOPrintWriterAccess;
|
|
||||||
private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
|
private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
|
||||||
private static JavaIOFilePermissionAccess javaIOFilePermissionAccess;
|
private static JavaIOFilePermissionAccess javaIOFilePermissionAccess;
|
||||||
private static JavaIORandomAccessFileAccess javaIORandomAccessFileAccess;
|
private static JavaIORandomAccessFileAccess javaIORandomAccessFileAccess;
|
||||||
|
@ -288,32 +286,6 @@ public class SharedSecrets {
|
||||||
return access;
|
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) {
|
public static void setJavaIOFileDescriptorAccess(JavaIOFileDescriptorAccess jiofda) {
|
||||||
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.nio.charset.UnsupportedCharsetException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import jdk.internal.misc.InternalLock;
|
|
||||||
|
|
||||||
public class StreamDecoder extends Reader {
|
public class StreamDecoder extends Reader {
|
||||||
|
|
||||||
private static final int MIN_BYTE_BUFFER_SIZE = 32;
|
private static final int MIN_BYTE_BUFFER_SIZE = 32;
|
||||||
|
@ -121,151 +119,95 @@ public class StreamDecoder extends Reader {
|
||||||
return read0();
|
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")
|
@SuppressWarnings("fallthrough")
|
||||||
private int lockedRead0() throws IOException {
|
private int read0() throws IOException {
|
||||||
// Return the leftover char, if there is one
|
synchronized (lock) {
|
||||||
if (haveLeftoverChar) {
|
// Return the leftover char, if there is one
|
||||||
haveLeftoverChar = false;
|
if (haveLeftoverChar) {
|
||||||
return leftoverChar;
|
haveLeftoverChar = false;
|
||||||
}
|
return leftoverChar;
|
||||||
|
}
|
||||||
|
|
||||||
// Convert more bytes
|
// Convert more bytes
|
||||||
char[] cb = new char[2];
|
char[] cb = new char[2];
|
||||||
int n = read(cb, 0, 2);
|
int n = read(cb, 0, 2);
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case -1:
|
case -1:
|
||||||
return -1;
|
return -1;
|
||||||
case 2:
|
case 2:
|
||||||
leftoverChar = cb[1];
|
leftoverChar = cb[1];
|
||||||
haveLeftoverChar = true;
|
haveLeftoverChar = true;
|
||||||
// FALL THROUGH
|
// FALL THROUGH
|
||||||
case 1:
|
case 1:
|
||||||
return cb[0];
|
return cb[0];
|
||||||
default:
|
default:
|
||||||
assert false : n;
|
assert false : n;
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read(char[] cbuf, int offset, int length) throws IOException {
|
public int read(char[] cbuf, int offset, int length) throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
int off = offset;
|
||||||
locker.lock();
|
int len = length;
|
||||||
try {
|
|
||||||
return lockedRead(cbuf, offset, length);
|
ensureOpen();
|
||||||
} finally {
|
if ((off < 0) || (off > cbuf.length) || (len < 0) ||
|
||||||
locker.unlock();
|
((off + len) > cbuf.length) || ((off + len) < 0)) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
} else {
|
if (len == 0)
|
||||||
synchronized (lock) {
|
return 0;
|
||||||
return lockedRead(cbuf, offset, length);
|
|
||||||
|
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 {
|
public boolean ready() throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
ensureOpen();
|
||||||
locker.lock();
|
return haveLeftoverChar || implReady();
|
||||||
try {
|
|
||||||
return lockedReady();
|
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
return lockedReady();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean lockedReady() throws IOException {
|
|
||||||
ensureOpen();
|
|
||||||
return haveLeftoverChar || implReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
if (closed)
|
||||||
locker.lock();
|
return;
|
||||||
try {
|
try {
|
||||||
lockedClose();
|
implClose();
|
||||||
} finally {
|
} 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 {
|
public void fillZeroToPosition() throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
Arrays.fill(bb.array(), bb.arrayOffset(),
|
||||||
locker.lock();
|
bb.arrayOffset() + bb.position(), (byte)0);
|
||||||
try {
|
|
||||||
lockedFillZeroToPosition();
|
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
lockedFillZeroToPosition();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void lockedFillZeroToPosition() {
|
|
||||||
Arrays.fill(bb.array(), bb.arrayOffset(), bb.arrayOffset() + bb.position(), (byte)0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Charset-based stream decoder impl --
|
// -- Charset-based stream decoder impl --
|
||||||
|
|
||||||
private final Charset cs;
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.CodingErrorAction;
|
||||||
import java.nio.charset.IllegalCharsetNameException;
|
import java.nio.charset.IllegalCharsetNameException;
|
||||||
import java.nio.charset.UnsupportedCharsetException;
|
import java.nio.charset.UnsupportedCharsetException;
|
||||||
import jdk.internal.misc.InternalLock;
|
|
||||||
|
|
||||||
public final class StreamEncoder extends Writer {
|
public final class StreamEncoder extends Writer {
|
||||||
|
|
||||||
|
@ -97,28 +96,14 @@ public final class StreamEncoder extends Writer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flushBuffer() throws IOException {
|
public void flushBuffer() throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
if (isOpen())
|
||||||
locker.lock();
|
implFlushBuffer();
|
||||||
try {
|
else
|
||||||
lockedFlushBuffer();
|
throw new IOException("Stream closed");
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
lockedFlushBuffer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void lockedFlushBuffer() throws IOException {
|
|
||||||
if (isOpen())
|
|
||||||
implFlushBuffer();
|
|
||||||
else
|
|
||||||
throw new IOException("Stream closed");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(int c) throws IOException {
|
public void write(int c) throws IOException {
|
||||||
char[] cbuf = new char[1];
|
char[] cbuf = new char[1];
|
||||||
cbuf[0] = (char) c;
|
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 {
|
public void write(char[] cbuf, int off, int len) throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
ensureOpen();
|
||||||
locker.lock();
|
if ((off < 0) || (off > cbuf.length) || (len < 0) ||
|
||||||
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) ||
|
|
||||||
((off + len) > cbuf.length) || ((off + len) < 0)) {
|
((off + len) > cbuf.length) || ((off + len) < 0)) {
|
||||||
throw new IndexOutOfBoundsException();
|
throw new IndexOutOfBoundsException();
|
||||||
} else if (len == 0) {
|
} else if (len == 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
implWrite(cbuf, off, len);
|
||||||
}
|
}
|
||||||
implWrite(cbuf, off, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(String str, int off, int len) throws IOException {
|
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 {
|
public void write(CharBuffer cb) throws IOException {
|
||||||
int position = cb.position();
|
int position = cb.position();
|
||||||
try {
|
try {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
ensureOpen();
|
||||||
locker.lock();
|
implWrite(cb);
|
||||||
try {
|
|
||||||
lockedWrite(cb);
|
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
lockedWrite(cb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
cb.position(position);
|
cb.position(position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void lockedWrite(CharBuffer cb) throws IOException {
|
|
||||||
ensureOpen();
|
|
||||||
implWrite(cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void flush() throws IOException {
|
public void flush() throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
ensureOpen();
|
||||||
locker.lock();
|
implFlush();
|
||||||
try {
|
|
||||||
lockedFlush();
|
|
||||||
} finally {
|
|
||||||
locker.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
lockedFlush();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void lockedFlush() throws IOException {
|
|
||||||
ensureOpen();
|
|
||||||
implFlush();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
Object lock = this.lock;
|
synchronized (lock) {
|
||||||
if (lock instanceof InternalLock locker) {
|
if (closed)
|
||||||
locker.lock();
|
return;
|
||||||
try {
|
try {
|
||||||
lockedClose();
|
implClose();
|
||||||
} finally {
|
} finally {
|
||||||
locker.unlock();
|
closed = true;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
synchronized (lock) {
|
|
||||||
lockedClose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void lockedClose() throws IOException {
|
|
||||||
if (closed)
|
|
||||||
return;
|
|
||||||
try {
|
|
||||||
implClose();
|
|
||||||
} finally {
|
|
||||||
closed = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
* @summary Basic tests for Process and Environment Variable code
|
* @summary Basic tests for Process and Environment Variable code
|
||||||
* @modules java.base/java.lang:open
|
* @modules java.base/java.lang:open
|
||||||
* java.base/java.io:open
|
* java.base/java.io:open
|
||||||
* java.base/jdk.internal.misc
|
|
||||||
* @requires !vm.musl
|
* @requires !vm.musl
|
||||||
* @requires vm.flagless
|
* @requires vm.flagless
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
|
@ -2676,17 +2675,6 @@ public class Basic {
|
||||||
else unexpected(t);}}
|
else unexpected(t);}}
|
||||||
|
|
||||||
static boolean isLocked(BufferedInputStream bis) throws Exception {
|
static boolean isLocked(BufferedInputStream bis) throws Exception {
|
||||||
Field lockField = BufferedInputStream.class.getDeclaredField("lock");
|
|
||||||
lockField.setAccessible(true);
|
|
||||||
var lock = (jdk.internal.misc.InternalLock) lockField.get(bis);
|
|
||||||
if (lock != null) {
|
|
||||||
if (lock.tryLock()) {
|
|
||||||
lock.unlock();
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Thread() {
|
return new Thread() {
|
||||||
volatile boolean unlocked;
|
volatile boolean unlocked;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue