mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
Merge
This commit is contained in:
commit
845f7823de
1200 changed files with 35255 additions and 79887 deletions
|
@ -48,6 +48,7 @@ class Constants {
|
|||
1.8 to 1.8.X 52,0
|
||||
1.9 to 1.9.X 53,0
|
||||
1.10 to 1.10.X 54,0
|
||||
1.11 to 1.11.X 55,0
|
||||
*/
|
||||
|
||||
public static final Package.Version JAVA_MIN_CLASS_VERSION =
|
||||
|
@ -71,6 +72,9 @@ class Constants {
|
|||
public static final Package.Version JAVA10_MAX_CLASS_VERSION =
|
||||
Package.Version.of(54, 00);
|
||||
|
||||
public static final Package.Version JAVA11_MAX_CLASS_VERSION =
|
||||
Package.Version.of(55, 00);
|
||||
|
||||
public static final int JAVA_PACKAGE_MAGIC = 0xCAFED00D;
|
||||
|
||||
public static final Package.Version JAVA5_PACKAGE_VERSION =
|
||||
|
@ -87,7 +91,7 @@ class Constants {
|
|||
|
||||
// upper limit, should point to the latest class version
|
||||
public static final Package.Version JAVA_MAX_CLASS_VERSION =
|
||||
JAVA10_MAX_CLASS_VERSION;
|
||||
JAVA11_MAX_CLASS_VERSION;
|
||||
|
||||
// upper limit should point to the latest package version, for version info!.
|
||||
public static final Package.Version MAX_PACKAGE_VERSION =
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2018, 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
|
||||
|
@ -162,11 +162,12 @@ class Driver {
|
|||
engProps.put((String) me.getKey(), (String) me.getValue());
|
||||
}
|
||||
} else if ("--version".equals(state)) {
|
||||
System.out.println(MessageFormat.format(RESOURCE.getString(DriverResource.VERSION), Driver.class.getName(), "1.31, 07/05/05"));
|
||||
System.out.println(MessageFormat.format(RESOURCE.getString(DriverResource.VERSION),
|
||||
Driver.class.getName(), "1.31, 07/05/05"));
|
||||
return;
|
||||
} else if ("--help".equals(state)) {
|
||||
printUsage(doPack, true, System.out);
|
||||
System.exit(1);
|
||||
System.exit(0);
|
||||
return;
|
||||
} else {
|
||||
break;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2018, 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
|
||||
|
@ -89,7 +89,7 @@ public class DriverResource extends ListResourceBundle {
|
|||
" -q, --quiet set verbosity to lowest level",
|
||||
" -l{F}, --log-file={F} output to the given log file, ",
|
||||
" or '-' for System.out",
|
||||
" -?, -h, --help print this message",
|
||||
" -?, -h, --help print this help message",
|
||||
" -V, --version print program version",
|
||||
" -J{X} pass option X to underlying Java VM",
|
||||
"",
|
||||
|
@ -118,7 +118,7 @@ public class DriverResource extends ListResourceBundle {
|
|||
" -q, --quiet set verbosity to lowest level",
|
||||
" -l{F}, --log-file={F} output to the given log file, or",
|
||||
" '-' for System.out",
|
||||
" -?, -h, --help print this message",
|
||||
" -?, -h, --help print this help message",
|
||||
" -V, --version print program version",
|
||||
" -J{X} pass option X to underlying Java VM"
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ package java.io;
|
|||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This class implements an output stream in which the data is
|
||||
|
@ -147,10 +148,7 @@ public class ByteArrayOutputStream extends OutputStream {
|
|||
* @param len the number of bytes to write.
|
||||
*/
|
||||
public synchronized void write(byte b[], int off, int len) {
|
||||
if ((off < 0) || (off > b.length) || (len < 0) ||
|
||||
((off + len) - b.length > 0)) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
Objects.checkFromIndexSize(off, len, b.length);
|
||||
ensureCapacity(count + len);
|
||||
System.arraycopy(b, off, buf, count, len);
|
||||
count += len;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2018, 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
|
||||
|
@ -2256,7 +2256,7 @@ public class File
|
|||
private transient volatile Path filePath;
|
||||
|
||||
/**
|
||||
* Returns a {@link Path java.nio.file.Path} object constructed from the
|
||||
* Returns a {@link Path java.nio.file.Path} object constructed from
|
||||
* this abstract path. The resulting {@code Path} is associated with the
|
||||
* {@link java.nio.file.FileSystems#getDefault default-filesystem}.
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2018, 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
|
||||
|
@ -25,7 +25,9 @@
|
|||
|
||||
package java.io;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
|
@ -53,6 +55,103 @@ public abstract class InputStream implements Closeable {
|
|||
|
||||
private static final int DEFAULT_BUFFER_SIZE = 8192;
|
||||
|
||||
/**
|
||||
* Returns a new {@code InputStream} that reads no bytes. The returned
|
||||
* stream is initially open. The stream is closed by calling the
|
||||
* {@code close()} method. Subsequent calls to {@code close()} have no
|
||||
* effect.
|
||||
*
|
||||
* <p> While the stream is open, the {@code available()}, {@code read()},
|
||||
* {@code read(byte[])}, {@code read(byte[], int, int)},
|
||||
* {@code readAllBytes()}, {@code readNBytes(byte[], int, int)},
|
||||
* {@code readNBytes(int)}, {@code skip(long)}, and
|
||||
* {@code transferTo()} methods all behave as if end of stream has been
|
||||
* reached. After the stream has been closed, these methods all throw
|
||||
* {@code IOException}.
|
||||
*
|
||||
* <p> The {@code markSupported()} method returns {@code false}. The
|
||||
* {@code mark()} method does nothing, and the {@code reset()} method
|
||||
* throws {@code IOException}.
|
||||
*
|
||||
* @return an {@code InputStream} which contains no bytes
|
||||
*
|
||||
* @since 11
|
||||
*/
|
||||
public static InputStream nullInputStream() {
|
||||
return new InputStream() {
|
||||
private volatile boolean closed;
|
||||
|
||||
private void ensureOpen() throws IOException {
|
||||
if (closed) {
|
||||
throw new IOException("Stream closed");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available () throws IOException {
|
||||
ensureOpen();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
ensureOpen();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
Objects.checkFromIndexSize(off, len, b.length);
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
ensureOpen();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] readAllBytes() throws IOException {
|
||||
ensureOpen();
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readNBytes(byte[] b, int off, int len)
|
||||
throws IOException {
|
||||
Objects.checkFromIndexSize(off, len, b.length);
|
||||
ensureOpen();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] readNBytes(int len) throws IOException {
|
||||
if (len < 0) {
|
||||
throw new IllegalArgumentException("len < 0");
|
||||
}
|
||||
ensureOpen();
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long n) throws IOException {
|
||||
ensureOpen();
|
||||
return 0L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long transferTo(OutputStream out) throws IOException {
|
||||
Objects.requireNonNull(out);
|
||||
ensureOpen();
|
||||
return 0L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
closed = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the next byte of data from the input stream. The value byte is
|
||||
* returned as an <code>int</code> in the range <code>0</code> to
|
||||
|
@ -144,8 +243,8 @@ public abstract class InputStream implements Closeable {
|
|||
* <code>b</code> and the number of bytes read before the exception
|
||||
* occurred is returned. The default implementation of this method blocks
|
||||
* until the requested amount of input data <code>len</code> has been read,
|
||||
* end of file is detected, or an exception is thrown. Subclasses are encouraged
|
||||
* to provide a more efficient implementation of this method.
|
||||
* end of file is detected, or an exception is thrown. Subclasses are
|
||||
* encouraged to provide a more efficient implementation of this method.
|
||||
*
|
||||
* @param b the buffer into which the data is read.
|
||||
* @param off the start offset in array <code>b</code>
|
||||
|
@ -164,7 +263,6 @@ public abstract class InputStream implements Closeable {
|
|||
* @see java.io.InputStream#read()
|
||||
*/
|
||||
public int read(byte b[], int off, int len) throws IOException {
|
||||
Objects.requireNonNull(b);
|
||||
Objects.checkFromIndexSize(off, len, b.length);
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
|
@ -220,39 +318,125 @@ public abstract class InputStream implements Closeable {
|
|||
* It is strongly recommended that the stream be promptly closed if an I/O
|
||||
* error occurs.
|
||||
*
|
||||
* @implSpec
|
||||
* This method invokes {@link #readNBytes(int)} with a length of
|
||||
* {@link Integer#MAX_VALUE}.
|
||||
*
|
||||
* @return a byte array containing the bytes read from this input stream
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws OutOfMemoryError if an array of the required size cannot be
|
||||
* allocated. For example, if an array larger than {@code 2GB} would
|
||||
* be required to store the bytes.
|
||||
* allocated.
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
public byte[] readAllBytes() throws IOException {
|
||||
byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
|
||||
int capacity = buf.length;
|
||||
int nread = 0;
|
||||
int n;
|
||||
for (;;) {
|
||||
// read to EOF which may read more or less than initial buffer size
|
||||
while ((n = read(buf, nread, capacity - nread)) > 0)
|
||||
nread += n;
|
||||
return readNBytes(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
// if the last call to read returned -1, then we're done
|
||||
if (n < 0)
|
||||
break;
|
||||
|
||||
// need to allocate a larger buffer
|
||||
if (capacity <= MAX_BUFFER_SIZE - capacity) {
|
||||
capacity = capacity << 1;
|
||||
} else {
|
||||
if (capacity == MAX_BUFFER_SIZE)
|
||||
throw new OutOfMemoryError("Required array size too large");
|
||||
capacity = MAX_BUFFER_SIZE;
|
||||
}
|
||||
buf = Arrays.copyOf(buf, capacity);
|
||||
/**
|
||||
* Reads up to a specified number of bytes from the input stream. This
|
||||
* method blocks until the requested number of bytes have been read, end
|
||||
* of stream is detected, or an exception is thrown. This method does not
|
||||
* close the input stream.
|
||||
*
|
||||
* <p> The length of the returned array equals the number of bytes read
|
||||
* from the stream. If {@code len} is zero, then no bytes are read and
|
||||
* an empty byte array is returned. Otherwise, up to {@code len} bytes
|
||||
* are read from the stream. Fewer than {@code len} bytes may be read if
|
||||
* end of stream is encountered.
|
||||
*
|
||||
* <p> When this stream reaches end of stream, further invocations of this
|
||||
* method will return an empty byte array.
|
||||
*
|
||||
* <p> Note that this method is intended for simple cases where it is
|
||||
* convenient to read the specified number of bytes into a byte array. The
|
||||
* total amount of memory allocated by this method is proportional to the
|
||||
* number of bytes read from the stream which is bounded by {@code len}.
|
||||
* Therefore, the method may be safely called with very large values of
|
||||
* {@code len} provided sufficient memory is available.
|
||||
*
|
||||
* <p> The behavior for the case where the input stream is <i>asynchronously
|
||||
* closed</i>, or the thread interrupted during the read, is highly input
|
||||
* stream specific, and therefore not specified.
|
||||
*
|
||||
* <p> If an I/O error occurs reading from the input stream, then it may do
|
||||
* so after some, but not all, bytes have been read. Consequently the input
|
||||
* stream may not be at end of stream and may be in an inconsistent state.
|
||||
* It is strongly recommended that the stream be promptly closed if an I/O
|
||||
* error occurs.
|
||||
*
|
||||
* @implNote
|
||||
* The number of bytes allocated to read data from this stream and return
|
||||
* the result is bounded by {@code 2*(long)len}, inclusive.
|
||||
*
|
||||
* @param len the maximum number of bytes to read
|
||||
* @return a byte array containing the bytes read from this input stream
|
||||
* @throws IllegalArgumentException if {@code length} is negative
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws OutOfMemoryError if an array of the required size cannot be
|
||||
* allocated.
|
||||
*
|
||||
* @since 11
|
||||
*/
|
||||
public byte[] readNBytes(int len) throws IOException {
|
||||
if (len < 0) {
|
||||
throw new IllegalArgumentException("len < 0");
|
||||
}
|
||||
return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
|
||||
|
||||
List<byte[]> bufs = null;
|
||||
byte[] result = null;
|
||||
int total = 0;
|
||||
int remaining = len;
|
||||
int n;
|
||||
do {
|
||||
byte[] buf = new byte[Math.min(remaining, DEFAULT_BUFFER_SIZE)];
|
||||
int nread = 0;
|
||||
|
||||
// read to EOF which may read more or less than buffer size
|
||||
while ((n = read(buf, nread,
|
||||
Math.min(buf.length - nread, remaining))) > 0) {
|
||||
nread += n;
|
||||
remaining -= n;
|
||||
}
|
||||
|
||||
if (nread > 0) {
|
||||
if (MAX_BUFFER_SIZE - total < nread) {
|
||||
throw new OutOfMemoryError("Required array size too large");
|
||||
}
|
||||
total += nread;
|
||||
if (result == null) {
|
||||
result = buf;
|
||||
} else {
|
||||
if (bufs == null) {
|
||||
bufs = new ArrayList<>();
|
||||
bufs.add(result);
|
||||
}
|
||||
bufs.add(buf);
|
||||
}
|
||||
}
|
||||
// if the last call to read returned -1 or the number of bytes
|
||||
// requested have been read then break
|
||||
} while (n >= 0 && remaining > 0);
|
||||
|
||||
if (bufs == null) {
|
||||
if (result == null) {
|
||||
return new byte[0];
|
||||
}
|
||||
return result.length == total ?
|
||||
result : Arrays.copyOf(result, total);
|
||||
}
|
||||
|
||||
result = new byte[total];
|
||||
int offset = 0;
|
||||
remaining = total;
|
||||
for (byte[] b : bufs) {
|
||||
int count = Math.min(b.length, remaining);
|
||||
System.arraycopy(b, 0, result, offset, count);
|
||||
offset += count;
|
||||
remaining -= count;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -299,7 +483,6 @@ public abstract class InputStream implements Closeable {
|
|||
* @since 9
|
||||
*/
|
||||
public int readNBytes(byte[] b, int off, int len) throws IOException {
|
||||
Objects.requireNonNull(b);
|
||||
Objects.checkFromIndexSize(off, len, b.length);
|
||||
|
||||
int n = 0;
|
||||
|
|
|
@ -1296,7 +1296,6 @@ public class ObjectInputStream
|
|||
* @throws InvalidClassException if the filter rejects creation
|
||||
*/
|
||||
private void checkArray(Class<?> arrayType, int arrayLength) throws InvalidClassException {
|
||||
Objects.requireNonNull(arrayType);
|
||||
if (! arrayType.isArray()) {
|
||||
throw new IllegalArgumentException("not an array type");
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2018, 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
|
||||
|
@ -46,6 +46,51 @@ import java.util.Objects;
|
|||
* @since 1.0
|
||||
*/
|
||||
public abstract class OutputStream implements Closeable, Flushable {
|
||||
/**
|
||||
* Returns a new {@code OutputStream} which discards all bytes. The
|
||||
* returned stream is initially open. The stream is closed by calling
|
||||
* the {@code close()} method. Subsequent calls to {@code close()} have
|
||||
* no effect.
|
||||
*
|
||||
* <p> While the stream is open, the {@code write(int)}, {@code
|
||||
* write(byte[])}, and {@code write(byte[], int, int)} methods do nothing.
|
||||
* After the stream has been closed, these methods all throw {@code
|
||||
* IOException}.
|
||||
*
|
||||
* <p> The {@code flush()} method does nothing.
|
||||
*
|
||||
* @return an {@code OutputStream} which discards all bytes
|
||||
*
|
||||
* @since 11
|
||||
*/
|
||||
public static OutputStream nullOutputStream() {
|
||||
return new OutputStream() {
|
||||
private volatile boolean closed;
|
||||
|
||||
private void ensureOpen() throws IOException {
|
||||
if (closed) {
|
||||
throw new IOException("Stream closed");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
ensureOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte b[], int off, int len) throws IOException {
|
||||
Objects.checkFromIndexSize(off, len, b.length);
|
||||
ensureOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
closed = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the specified byte to this output stream. The general
|
||||
* contract for <code>write</code> is that one byte is written
|
||||
|
@ -106,7 +151,6 @@ public abstract class OutputStream implements Closeable, Flushable {
|
|||
* stream is closed.
|
||||
*/
|
||||
public void write(byte b[], int off, int len) throws IOException {
|
||||
Objects.requireNonNull(b);
|
||||
Objects.checkFromIndexSize(off, len, b.length);
|
||||
// len == 0 condition implicitly handled by loop bounds
|
||||
for (int i = 0 ; i < len ; i++) {
|
||||
|
|
|
@ -1876,14 +1876,15 @@ public abstract class ClassLoader {
|
|||
* value until the system is fully initialized.
|
||||
*
|
||||
* <p> The name of the built-in system class loader is {@code "app"}.
|
||||
* The class path used by the built-in system class loader is determined
|
||||
* by the system property "{@code java.class.path}" during early
|
||||
* initialization of the VM. If the system property is not defined,
|
||||
* or its value is an empty string, then there is no class path
|
||||
* when the initial module is a module on the application module path,
|
||||
* i.e. <em>a named module</em>. If the initial module is not on
|
||||
* the application module path then the class path defaults to
|
||||
* the current working directory.
|
||||
* The system property "{@code java.class.path}" is read during early
|
||||
* initialization of the VM to determine the class path.
|
||||
* An empty value of "{@code java.class.path}" property is interpreted
|
||||
* differently depending on whether the initial module (the module
|
||||
* containing the main class) is named or unnamed:
|
||||
* If named, the built-in system class loader will have no class path and
|
||||
* will search for classes and resources using the application module path;
|
||||
* otherwise, if unnamed, it will set the class path to the current
|
||||
* working directory.
|
||||
*
|
||||
* @return The system {@code ClassLoader}
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2018, 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
|
||||
|
@ -1099,16 +1099,23 @@ public class Runtime {
|
|||
m.group(VersionPattern.OPT_GROUP));
|
||||
|
||||
// empty '+'
|
||||
if ((m.group(VersionPattern.PLUS_GROUP) != null)
|
||||
&& !build.isPresent()) {
|
||||
if (optional.isPresent()) {
|
||||
if (pre.isPresent())
|
||||
throw new IllegalArgumentException("'+' found with"
|
||||
+ " pre-release and optional components:'" + s
|
||||
+ "'");
|
||||
if (!build.isPresent()) {
|
||||
if (m.group(VersionPattern.PLUS_GROUP) != null) {
|
||||
if (optional.isPresent()) {
|
||||
if (pre.isPresent())
|
||||
throw new IllegalArgumentException("'+' found with"
|
||||
+ " pre-release and optional components:'" + s
|
||||
+ "'");
|
||||
} else {
|
||||
throw new IllegalArgumentException("'+' found with neither"
|
||||
+ " build or optional components: '" + s + "'");
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("'+' found with neither"
|
||||
+ " build or optional components: '" + s + "'");
|
||||
if (optional.isPresent() && !pre.isPresent()) {
|
||||
throw new IllegalArgumentException("optional component"
|
||||
+ " must be preceeded by a pre-release component"
|
||||
+ " or '+': '" + s + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Version(List.of(version), pre, build, optional);
|
||||
|
|
|
@ -631,7 +631,8 @@ public final class System {
|
|||
* <tr><th scope="row"><code>java.class.version</code></th>
|
||||
* <td>Java class format version number</td></tr>
|
||||
* <tr><th scope="row"><code>java.class.path</code></th>
|
||||
* <td>Java class path</td></tr>
|
||||
* <td>Java class path (refer to
|
||||
* {@link ClassLoader#getSystemClassLoader()} for details)</td></tr>
|
||||
* <tr><th scope="row"><code>java.library.path</code></th>
|
||||
* <td>List of paths to search when loading libraries</td></tr>
|
||||
* <tr><th scope="row"><code>java.io.tmpdir</code></th>
|
||||
|
|
|
@ -166,15 +166,8 @@ class VersionProps {
|
|||
* Print version info.
|
||||
*/
|
||||
private static void print(boolean err, boolean newln) {
|
||||
boolean isHeadless = false;
|
||||
PrintStream ps = err ? System.err : System.out;
|
||||
|
||||
/* Report that we're running headless if the property is true */
|
||||
String headless = System.getProperty("java.awt.headless");
|
||||
if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) {
|
||||
isHeadless = true;
|
||||
}
|
||||
|
||||
/* First line: platform version. */
|
||||
if (err) {
|
||||
ps.println(launcher_name + " version \"" + java_version + "\""
|
||||
|
|
|
@ -1667,6 +1667,7 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
|
|||
/** Craft a LambdaForm customized for this particular MethodHandle */
|
||||
/*non-public*/
|
||||
void customize() {
|
||||
final LambdaForm form = this.form;
|
||||
if (form.customized == null) {
|
||||
LambdaForm newForm = form.customize(this);
|
||||
updateForm(newForm);
|
||||
|
|
|
@ -3766,6 +3766,7 @@ assertEquals("xy", h3.invoke("x", "y", 1, "a", "b", "c"));
|
|||
* specified in the elements of the {@code filters} array.
|
||||
* The first element of the filter array corresponds to the {@code pos}
|
||||
* argument of the target, and so on in sequence.
|
||||
* The filter functions are invoked in left to right order.
|
||||
* <p>
|
||||
* Null arguments in the array are treated as identity functions,
|
||||
* and the corresponding arguments left unchanged.
|
||||
|
@ -3836,11 +3837,12 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
|
|||
MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
|
||||
filterArgumentsCheckArity(target, pos, filters);
|
||||
MethodHandle adapter = target;
|
||||
int curPos = pos-1; // pre-incremented
|
||||
for (MethodHandle filter : filters) {
|
||||
curPos += 1;
|
||||
// process filters in reverse order so that the invocation of
|
||||
// the resulting adapter will invoke the filters in left-to-right order
|
||||
for (int i = filters.length - 1; i >= 0; --i) {
|
||||
MethodHandle filter = filters[i];
|
||||
if (filter == null) continue; // ignore null elements of filters
|
||||
adapter = filterArgument(adapter, curPos, filter);
|
||||
adapter = filterArgument(adapter, pos + i, filter);
|
||||
}
|
||||
return adapter;
|
||||
}
|
||||
|
|
|
@ -2521,7 +2521,7 @@ public class ModuleDescriptor
|
|||
* the {@code packageFinder} throws an {@link UncheckedIOException} then
|
||||
* {@link IOException} cause will be re-thrown. </p>
|
||||
*
|
||||
* <p> The module descriptor is read from the buffer stating at index
|
||||
* <p> The module descriptor is read from the buffer starting at index
|
||||
* {@code p}, where {@code p} is the buffer's {@link ByteBuffer#position()
|
||||
* position} when this method is invoked. Upon return the buffer's position
|
||||
* will be equal to {@code p + n} where {@code n} is the number of bytes
|
||||
|
|
|
@ -140,14 +140,6 @@ public abstract class Reference<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* system property to disable clearing before enqueuing.
|
||||
*/
|
||||
private static final class ClearBeforeEnqueue {
|
||||
static final boolean DISABLE =
|
||||
Boolean.getBoolean("jdk.lang.ref.disableClearBeforeEnqueue");
|
||||
}
|
||||
|
||||
/*
|
||||
* Atomically get and clear (set to null) the VM's pending list.
|
||||
*/
|
||||
|
@ -299,8 +291,7 @@ public abstract class Reference<T> {
|
|||
* it was not registered with a queue when it was created
|
||||
*/
|
||||
public boolean enqueue() {
|
||||
if (!ClearBeforeEnqueue.DISABLE)
|
||||
this.referent = null;
|
||||
this.referent = null;
|
||||
return this.queue.enqueue(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2018, 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
|
||||
|
@ -26,11 +26,11 @@ package java.net;
|
|||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.security.AccessController;
|
||||
import sun.net.ResourceManager;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import sun.net.ResourceManager;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
|
@ -115,6 +115,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
|
|||
fd = new FileDescriptor();
|
||||
try {
|
||||
datagramSocketCreate();
|
||||
SocketCleanable.register(fd);
|
||||
} catch (SocketException ioe) {
|
||||
ResourceManager.afterUdpClose();
|
||||
fd = null;
|
||||
|
@ -265,6 +266,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
|
|||
*/
|
||||
protected void close() {
|
||||
if (fd != null) {
|
||||
SocketCleanable.unregister(fd);
|
||||
datagramSocketClose();
|
||||
ResourceManager.afterUdpClose();
|
||||
fd = null;
|
||||
|
@ -275,11 +277,6 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
|
|||
return (fd == null) ? true : false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
protected void finalize() {
|
||||
close();
|
||||
}
|
||||
|
||||
/**
|
||||
* set a value - since we only support (setting) binary options
|
||||
* here, o must be a Boolean
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2018, 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
|
||||
|
@ -25,17 +25,18 @@
|
|||
|
||||
package java.net;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.FileDescriptor;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import sun.net.ConnectionResetException;
|
||||
import sun.net.NetHooks;
|
||||
import sun.net.ResourceManager;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Default Socket Implementation. This implementation does
|
||||
|
@ -136,6 +137,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
|
|||
fd = new FileDescriptor();
|
||||
try {
|
||||
socketCreate(false);
|
||||
SocketCleanable.register(fd);
|
||||
} catch (IOException ioe) {
|
||||
ResourceManager.afterUdpClose();
|
||||
fd = null;
|
||||
|
@ -144,6 +146,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
|
|||
} else {
|
||||
fd = new FileDescriptor();
|
||||
socketCreate(true);
|
||||
SocketCleanable.register(fd);
|
||||
}
|
||||
if (socket != null)
|
||||
socket.setCreated();
|
||||
|
@ -643,14 +646,6 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
|
|||
socketSendUrgentData (data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up if the user forgets to close it.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
protected void finalize() throws IOException {
|
||||
close();
|
||||
}
|
||||
|
||||
/*
|
||||
* "Acquires" and returns the FileDescriptor for this impl
|
||||
*
|
||||
|
@ -748,6 +743,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
|
|||
* Close the socket (and release the file descriptor).
|
||||
*/
|
||||
protected void socketClose() throws IOException {
|
||||
SocketCleanable.unregister(fd);
|
||||
socketClose0(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2018, 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
|
||||
|
@ -595,7 +595,7 @@ class Inet6Address extends InetAddress {
|
|||
}
|
||||
|
||||
ObjectInputStream.GetField gf = s.readFields();
|
||||
byte[] ipaddress = (byte[])gf.get("ipaddress", null);
|
||||
byte[] ipaddress = (byte[])gf.get("ipaddress", new byte[0]);
|
||||
int scope_id = gf.get("scope_id", -1);
|
||||
boolean scope_id_set = gf.get("scope_id_set", false);
|
||||
boolean scope_ifname_set = gf.get("scope_ifname_set", false);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2018, 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
|
||||
|
@ -317,10 +317,9 @@ public class InetSocketAddress
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Gets the {@code InetAddress}.
|
||||
*
|
||||
* @return the InetAdress or {@code null} if it is unresolved.
|
||||
* @return the InetAddress or {@code null} if it is unresolved.
|
||||
*/
|
||||
public final InetAddress getAddress() {
|
||||
return holder.getAddress();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2018, 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
|
||||
|
@ -549,6 +549,7 @@ class ServerSocket implements java.io.Closeable {
|
|||
si.address = new InetAddress();
|
||||
si.fd = new FileDescriptor();
|
||||
getImpl().accept(si);
|
||||
SocketCleanable.register(si.fd); // raw fd has been set
|
||||
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
if (security != null) {
|
||||
|
|
107
src/java.base/share/classes/java/net/SocketCleanable.java
Normal file
107
src/java.base/share/classes/java/net/SocketCleanable.java
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (c) 2018, 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 java.net;
|
||||
|
||||
import jdk.internal.misc.JavaIOFileDescriptorAccess;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.ref.CleanerFactory;
|
||||
import jdk.internal.ref.PhantomCleanable;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.ref.Cleaner;
|
||||
|
||||
|
||||
/**
|
||||
* Cleanup for a socket/datagramsocket FileDescriptor when it becomes phantom reachable.
|
||||
* Create a cleanup if the raw fd != -1. Windows closes sockets using the fd.
|
||||
* Subclassed from {@code PhantomCleanable} so that {@code clear} can be
|
||||
* called to disable the cleanup when the socket fd is closed by any means
|
||||
* other than calling {@link FileDescriptor#close}.
|
||||
* Otherwise, it would incorrectly close the handle or fd after it has been reused.
|
||||
*/
|
||||
final class SocketCleanable extends PhantomCleanable<Object> {
|
||||
|
||||
// Access to FileDescriptor internals
|
||||
private static final JavaIOFileDescriptorAccess fdAccess =
|
||||
SharedSecrets.getJavaIOFileDescriptorAccess();
|
||||
|
||||
// Native function to call NET_SocketClose(fd)
|
||||
private static native void cleanupClose0(int fd) throws IOException;
|
||||
|
||||
// The raw fd to close
|
||||
private final int fd;
|
||||
|
||||
/**
|
||||
* Register a socket specific Cleanable with the FileDescriptor
|
||||
* if the FileDescriptor is non-null and the raw fd is != -1.
|
||||
*
|
||||
* @param fdo the FileDescriptor; may be null
|
||||
*/
|
||||
static void register(FileDescriptor fdo) {
|
||||
if (fdo != null) {
|
||||
int fd = fdAccess.get(fdo);
|
||||
if (fd != -1) {
|
||||
fdAccess.registerCleanup(fdo,
|
||||
new SocketCleanable(fdo, CleanerFactory.cleaner(), fd));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a Cleanable from the FileDescriptor.
|
||||
* @param fdo the FileDescriptor; may be null
|
||||
*/
|
||||
static void unregister(FileDescriptor fdo) {
|
||||
if (fdo != null) {
|
||||
fdAccess.unregisterCleanup(fdo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for a phantom cleanable reference.
|
||||
*
|
||||
* @param obj the object to monitor
|
||||
* @param cleaner the cleaner
|
||||
* @param fd file descriptor to close
|
||||
*/
|
||||
private SocketCleanable(Object obj, Cleaner cleaner, int fd) {
|
||||
super(obj, cleaner);
|
||||
this.fd = fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the native handle or fd.
|
||||
*/
|
||||
@Override
|
||||
protected void performCleanup() {
|
||||
try {
|
||||
cleanupClose0(fd);
|
||||
} catch (IOException ioe) {
|
||||
throw new UncheckedIOException("close", ioe);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -63,38 +63,38 @@ class Bits { // package-private
|
|||
|
||||
// -- Unsafe access --
|
||||
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||
|
||||
static Unsafe unsafe() {
|
||||
return unsafe;
|
||||
return UNSAFE;
|
||||
}
|
||||
|
||||
|
||||
// -- Processor and memory-system properties --
|
||||
|
||||
private static final ByteOrder byteOrder
|
||||
= unsafe.isBigEndian() ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
|
||||
private static final ByteOrder BYTE_ORDER
|
||||
= UNSAFE.isBigEndian() ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
|
||||
|
||||
static ByteOrder byteOrder() {
|
||||
return byteOrder;
|
||||
return BYTE_ORDER;
|
||||
}
|
||||
|
||||
private static int pageSize = -1;
|
||||
private static int PAGE_SIZE = -1;
|
||||
|
||||
static int pageSize() {
|
||||
if (pageSize == -1)
|
||||
pageSize = unsafe().pageSize();
|
||||
return pageSize;
|
||||
if (PAGE_SIZE == -1)
|
||||
PAGE_SIZE = unsafe().pageSize();
|
||||
return PAGE_SIZE;
|
||||
}
|
||||
|
||||
static int pageCount(long size) {
|
||||
return (int)(size + (long)pageSize() - 1L) / pageSize();
|
||||
}
|
||||
|
||||
private static boolean unaligned = unsafe.unalignedAccess();
|
||||
private static boolean UNALIGNED = UNSAFE.unalignedAccess();
|
||||
|
||||
static boolean unaligned() {
|
||||
return unaligned;
|
||||
return UNALIGNED;
|
||||
}
|
||||
|
||||
|
||||
|
@ -103,11 +103,11 @@ class Bits { // package-private
|
|||
// A user-settable upper limit on the maximum amount of allocatable
|
||||
// direct buffer memory. This value may be changed during VM
|
||||
// initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".
|
||||
private static volatile long maxMemory = VM.maxDirectMemory();
|
||||
private static final AtomicLong reservedMemory = new AtomicLong();
|
||||
private static final AtomicLong totalCapacity = new AtomicLong();
|
||||
private static final AtomicLong count = new AtomicLong();
|
||||
private static volatile boolean memoryLimitSet;
|
||||
private static volatile long MAX_MEMORY = VM.maxDirectMemory();
|
||||
private static final AtomicLong RESERVED_MEMORY = new AtomicLong();
|
||||
private static final AtomicLong TOTAL_CAPACITY = new AtomicLong();
|
||||
private static final AtomicLong COUNT = new AtomicLong();
|
||||
private static volatile boolean MEMORY_LIMIT_SET;
|
||||
|
||||
// max. number of sleeps during try-reserving with exponentially
|
||||
// increasing delay before throwing OutOfMemoryError:
|
||||
|
@ -120,9 +120,9 @@ class Bits { // package-private
|
|||
// which a process may access. All sizes are specified in bytes.
|
||||
static void reserveMemory(long size, int cap) {
|
||||
|
||||
if (!memoryLimitSet && VM.initLevel() >= 1) {
|
||||
maxMemory = VM.maxDirectMemory();
|
||||
memoryLimitSet = true;
|
||||
if (!MEMORY_LIMIT_SET && VM.initLevel() >= 1) {
|
||||
MAX_MEMORY = VM.maxDirectMemory();
|
||||
MEMORY_LIMIT_SET = true;
|
||||
}
|
||||
|
||||
// optimist!
|
||||
|
@ -200,10 +200,10 @@ class Bits { // package-private
|
|||
// actual memory usage, which will differ when buffers are page
|
||||
// aligned.
|
||||
long totalCap;
|
||||
while (cap <= maxMemory - (totalCap = totalCapacity.get())) {
|
||||
if (totalCapacity.compareAndSet(totalCap, totalCap + cap)) {
|
||||
reservedMemory.addAndGet(size);
|
||||
count.incrementAndGet();
|
||||
while (cap <= MAX_MEMORY - (totalCap = TOTAL_CAPACITY.get())) {
|
||||
if (TOTAL_CAPACITY.compareAndSet(totalCap, totalCap + cap)) {
|
||||
RESERVED_MEMORY.addAndGet(size);
|
||||
COUNT.incrementAndGet();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -213,9 +213,9 @@ class Bits { // package-private
|
|||
|
||||
|
||||
static void unreserveMemory(long size, int cap) {
|
||||
long cnt = count.decrementAndGet();
|
||||
long reservedMem = reservedMemory.addAndGet(-size);
|
||||
long totalCap = totalCapacity.addAndGet(-cap);
|
||||
long cnt = COUNT.decrementAndGet();
|
||||
long reservedMem = RESERVED_MEMORY.addAndGet(-size);
|
||||
long totalCap = TOTAL_CAPACITY.addAndGet(-cap);
|
||||
assert cnt >= 0 && reservedMem >= 0 && totalCap >= 0;
|
||||
}
|
||||
|
||||
|
@ -234,15 +234,15 @@ class Bits { // package-private
|
|||
}
|
||||
@Override
|
||||
public long getCount() {
|
||||
return Bits.count.get();
|
||||
return Bits.COUNT.get();
|
||||
}
|
||||
@Override
|
||||
public long getTotalCapacity() {
|
||||
return Bits.totalCapacity.get();
|
||||
return Bits.TOTAL_CAPACITY.get();
|
||||
}
|
||||
@Override
|
||||
public long getMemoryUsed() {
|
||||
return Bits.reservedMemory.get();
|
||||
return Bits.RESERVED_MEMORY.get();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
package java.nio;
|
||||
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
import java.util.Spliterator;
|
||||
|
||||
|
@ -181,6 +182,8 @@ import java.util.Spliterator;
|
|||
*/
|
||||
|
||||
public abstract class Buffer {
|
||||
// Cached unsafe-access object
|
||||
static final Unsafe UNSAFE = Bits.unsafe();
|
||||
|
||||
/**
|
||||
* The characteristics of Spliterators that traverse and split elements
|
||||
|
@ -616,6 +619,14 @@ public abstract class Buffer {
|
|||
|
||||
// -- Package-private methods for bounds checking, etc. --
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the base reference, paired with the address
|
||||
* field, which in combination can be used for unsafe access into a heap
|
||||
* buffer or direct byte buffer (and views of).
|
||||
*/
|
||||
abstract Object base();
|
||||
|
||||
/**
|
||||
* Checks the current position against the limit, throwing a {@link
|
||||
* BufferUnderflowException} if it is not smaller than the limit, and then
|
||||
|
|
198
src/java.base/share/classes/java/nio/BufferMismatch.java
Normal file
198
src/java.base/share/classes/java/nio/BufferMismatch.java
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 java.nio;
|
||||
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
|
||||
/**
|
||||
* Mismatch methods for buffers
|
||||
*/
|
||||
final class BufferMismatch {
|
||||
|
||||
static int mismatch(ByteBuffer a, int aOff, ByteBuffer b, int bOff, int length) {
|
||||
int i = 0;
|
||||
if (length > 7) {
|
||||
i = ArraysSupport.vectorizedMismatch(
|
||||
a.base(), a.address + aOff,
|
||||
b.base(), b.address + bOff,
|
||||
length,
|
||||
ArraysSupport.LOG2_ARRAY_BYTE_INDEX_SCALE);
|
||||
if (i >= 0) return i;
|
||||
i = length - ~i;
|
||||
}
|
||||
for (; i < length; i++) {
|
||||
if (a.get(aOff + i) != b.get(bOff + i))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mismatch(CharBuffer a, int aOff, CharBuffer b, int bOff, int length) {
|
||||
int i = 0;
|
||||
// Ensure only heap or off-heap buffer instances use the
|
||||
// vectorized mismatch. If either buffer is a StringCharBuffer
|
||||
// (order is null) then the slow path is taken
|
||||
if (length > 3 && a.charRegionOrder() == b.charRegionOrder()
|
||||
&& a.charRegionOrder() != null && b.charRegionOrder() != null) {
|
||||
i = ArraysSupport.vectorizedMismatch(
|
||||
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_CHAR_INDEX_SCALE),
|
||||
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_CHAR_INDEX_SCALE),
|
||||
length,
|
||||
ArraysSupport.LOG2_ARRAY_CHAR_INDEX_SCALE);
|
||||
if (i >= 0) return i;
|
||||
i = length - ~i;
|
||||
}
|
||||
for (; i < length; i++) {
|
||||
if (a.get(aOff + i) != b.get(bOff + i))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mismatch(ShortBuffer a, int aOff, ShortBuffer b, int bOff, int length) {
|
||||
int i = 0;
|
||||
if (length > 3 && a.order() == b.order()) {
|
||||
i = ArraysSupport.vectorizedMismatch(
|
||||
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_SHORT_INDEX_SCALE),
|
||||
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_SHORT_INDEX_SCALE),
|
||||
length,
|
||||
ArraysSupport.LOG2_ARRAY_SHORT_INDEX_SCALE);
|
||||
if (i >= 0) return i;
|
||||
i = length - ~i;
|
||||
}
|
||||
for (; i < length; i++) {
|
||||
if (a.get(aOff + i) != b.get(bOff + i))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mismatch(IntBuffer a, int aOff, IntBuffer b, int bOff, int length) {
|
||||
int i = 0;
|
||||
if (length > 1 && a.order() == b.order()) {
|
||||
i = ArraysSupport.vectorizedMismatch(
|
||||
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_INT_INDEX_SCALE),
|
||||
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_INT_INDEX_SCALE),
|
||||
length,
|
||||
ArraysSupport.LOG2_ARRAY_INT_INDEX_SCALE);
|
||||
if (i >= 0) return i;
|
||||
i = length - ~i;
|
||||
}
|
||||
for (; i < length; i++) {
|
||||
if (a.get(aOff + i) != b.get(bOff + i))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mismatch(FloatBuffer a, int aOff, FloatBuffer b, int bOff, int length) {
|
||||
int i = 0;
|
||||
if (length > 1 && a.order() == b.order()) {
|
||||
i = ArraysSupport.vectorizedMismatch(
|
||||
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE),
|
||||
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE),
|
||||
length,
|
||||
ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE);
|
||||
// Mismatched
|
||||
if (i >= 0) {
|
||||
// Check if mismatch is not associated with two NaN values; and
|
||||
// is not associated with +0 and -0
|
||||
float av = a.get(aOff + i);
|
||||
float bv = b.get(bOff + i);
|
||||
if (av != bv && (!Float.isNaN(av) || !Float.isNaN(bv)))
|
||||
return i;
|
||||
|
||||
// Fall back to slow mechanism
|
||||
// ISSUE: Consider looping over vectorizedMismatch adjusting ranges
|
||||
// However, requires that returned value be relative to input ranges
|
||||
i++;
|
||||
}
|
||||
// Matched
|
||||
else {
|
||||
i = length - ~i;
|
||||
}
|
||||
}
|
||||
for (; i < length; i++) {
|
||||
float av = a.get(aOff + i);
|
||||
float bv = b.get(bOff + i);
|
||||
if (av != bv && (!Float.isNaN(av) || !Float.isNaN(bv)))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mismatch(LongBuffer a, int aOff, LongBuffer b, int bOff, int length) {
|
||||
int i = 0;
|
||||
if (length > 0 && a.order() == b.order()) {
|
||||
i = ArraysSupport.vectorizedMismatch(
|
||||
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_LONG_INDEX_SCALE),
|
||||
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_LONG_INDEX_SCALE),
|
||||
length,
|
||||
ArraysSupport.LOG2_ARRAY_LONG_INDEX_SCALE);
|
||||
return i >= 0 ? i : -1;
|
||||
}
|
||||
for (; i < length; i++) {
|
||||
if (a.get(aOff + i) != b.get(bOff + i))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mismatch(DoubleBuffer a, int aOff, DoubleBuffer b, int bOff, int length) {
|
||||
int i = 0;
|
||||
if (length > 0 && a.order() == b.order()) {
|
||||
i = ArraysSupport.vectorizedMismatch(
|
||||
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE),
|
||||
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE),
|
||||
length,
|
||||
ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE);
|
||||
// Mismatched
|
||||
if (i >= 0) {
|
||||
// Check if mismatch is not associated with two NaN values; and
|
||||
// is not associated with +0 and -0
|
||||
double av = a.get(aOff + i);
|
||||
double bv = b.get(bOff + i);
|
||||
if (av != bv && (!Double.isNaN(av) || !Double.isNaN(bv)))
|
||||
return i;
|
||||
|
||||
// Fall back to slow mechanism
|
||||
// ISSUE: Consider looping over vectorizedMismatch adjusting ranges
|
||||
// However, requires that returned value be relative to input ranges
|
||||
i++;
|
||||
}
|
||||
// Matched
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
for (; i < length; i++) {
|
||||
double av = a.get(aOff + i);
|
||||
double bv = b.get(bOff + i);
|
||||
if (av != bv && (!Double.isNaN(av) || !Double.isNaN(bv)))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
|
@ -36,9 +36,6 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
|
|||
|
||||
#if[rw]
|
||||
|
||||
// Cached unsafe-access object
|
||||
private static final Unsafe unsafe = Bits.unsafe();
|
||||
|
||||
protected final ByteBuffer bb;
|
||||
|
||||
#end[rw]
|
||||
|
@ -74,6 +71,11 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
|
|||
#end[rw]
|
||||
}
|
||||
|
||||
@Override
|
||||
Object base() {
|
||||
return bb.hb;
|
||||
}
|
||||
|
||||
public $Type$Buffer slice() {
|
||||
int pos = this.position();
|
||||
int lim = this.limit();
|
||||
|
@ -117,20 +119,20 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
|
|||
}
|
||||
|
||||
public $type$ get() {
|
||||
$memtype$ x = unsafe.get$Memtype$Unaligned(bb.hb, byteOffset(nextGetIndex()),
|
||||
$memtype$ x = UNSAFE.get$Memtype$Unaligned(bb.hb, byteOffset(nextGetIndex()),
|
||||
{#if[boB]?true:false});
|
||||
return $fromBits$(x);
|
||||
}
|
||||
|
||||
public $type$ get(int i) {
|
||||
$memtype$ x = unsafe.get$Memtype$Unaligned(bb.hb, byteOffset(checkIndex(i)),
|
||||
$memtype$ x = UNSAFE.get$Memtype$Unaligned(bb.hb, byteOffset(checkIndex(i)),
|
||||
{#if[boB]?true:false});
|
||||
return $fromBits$(x);
|
||||
}
|
||||
|
||||
#if[streamableType]
|
||||
$type$ getUnchecked(int i) {
|
||||
$memtype$ x = unsafe.get$Memtype$Unaligned(bb.hb, byteOffset(i),
|
||||
$memtype$ x = UNSAFE.get$Memtype$Unaligned(bb.hb, byteOffset(i),
|
||||
{#if[boB]?true:false});
|
||||
return $fromBits$(x);
|
||||
}
|
||||
|
@ -141,7 +143,7 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
|
|||
public $Type$Buffer put($type$ x) {
|
||||
#if[rw]
|
||||
$memtype$ y = $toBits$(x);
|
||||
unsafe.put$Memtype$Unaligned(bb.hb, byteOffset(nextPutIndex()), y,
|
||||
UNSAFE.put$Memtype$Unaligned(bb.hb, byteOffset(nextPutIndex()), y,
|
||||
{#if[boB]?true:false});
|
||||
return this;
|
||||
#else[rw]
|
||||
|
@ -152,7 +154,7 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
|
|||
public $Type$Buffer put(int i, $type$ x) {
|
||||
#if[rw]
|
||||
$memtype$ y = $toBits$(x);
|
||||
unsafe.put$Memtype$Unaligned(bb.hb, byteOffset(checkIndex(i)), y,
|
||||
UNSAFE.put$Memtype$Unaligned(bb.hb, byteOffset(checkIndex(i)), y,
|
||||
{#if[boB]?true:false});
|
||||
return this;
|
||||
#else[rw]
|
||||
|
@ -241,4 +243,9 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
|
|||
#end[boL]
|
||||
}
|
||||
|
||||
#if[char]
|
||||
ByteOrder charRegionOrder() {
|
||||
return order();
|
||||
}
|
||||
#end[char]
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ class XXX {
|
|||
#if[rw]
|
||||
|
||||
private $type$ get$Type$(long a) {
|
||||
$memtype$ x = unsafe.get$Memtype$Unaligned(null, a, bigEndian);
|
||||
$memtype$ x = UNSAFE.get$Memtype$Unaligned(null, a, bigEndian);
|
||||
return $fromBits$(x);
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ class XXX {
|
|||
private ByteBuffer put$Type$(long a, $type$ x) {
|
||||
#if[rw]
|
||||
$memtype$ y = $toBits$(x);
|
||||
unsafe.put$Memtype$Unaligned(null, a, y, bigEndian);
|
||||
UNSAFE.put$Memtype$Unaligned(null, a, y, bigEndian);
|
||||
return this;
|
||||
#else[rw]
|
||||
throw new ReadOnlyBufferException();
|
||||
|
@ -81,7 +81,7 @@ class XXX {
|
|||
int rem = (off <= lim ? lim - off : 0);
|
||||
|
||||
int size = rem >> $LG_BYTES_PER_VALUE$;
|
||||
if (!unaligned && ((address + off) % $BYTES_PER_VALUE$ != 0)) {
|
||||
if (!UNALIGNED && ((address + off) % $BYTES_PER_VALUE$ != 0)) {
|
||||
return (bigEndian
|
||||
? ($Type$Buffer)(new ByteBufferAs$Type$Buffer$RW$B(this,
|
||||
-1,
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
package java.nio;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.internal.misc.VM;
|
||||
import jdk.internal.ref.Cleaner;
|
||||
import sun.nio.ch.DirectBuffer;
|
||||
|
@ -45,14 +44,11 @@ class Direct$Type$Buffer$RW$$BO$
|
|||
|
||||
#if[rw]
|
||||
|
||||
// Cached unsafe-access object
|
||||
protected static final Unsafe unsafe = Bits.unsafe();
|
||||
|
||||
// Cached array base offset
|
||||
private static final long arrayBaseOffset = (long)unsafe.arrayBaseOffset($type$[].class);
|
||||
private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset($type$[].class);
|
||||
|
||||
// Cached unaligned-access capability
|
||||
protected static final boolean unaligned = Bits.unaligned();
|
||||
protected static final boolean UNALIGNED = Bits.unaligned();
|
||||
|
||||
// Base address, used in all indexing calculations
|
||||
// NOTE: moved up to Buffer.java for speed in JNI GetDirectBufferAddress
|
||||
|
@ -73,8 +69,6 @@ class Direct$Type$Buffer$RW$$BO$
|
|||
implements Runnable
|
||||
{
|
||||
|
||||
private static Unsafe unsafe = Unsafe.getUnsafe();
|
||||
|
||||
private long address;
|
||||
private long size;
|
||||
private int capacity;
|
||||
|
@ -91,7 +85,7 @@ class Direct$Type$Buffer$RW$$BO$
|
|||
// Paranoia
|
||||
return;
|
||||
}
|
||||
unsafe.freeMemory(address);
|
||||
UNSAFE.freeMemory(address);
|
||||
address = 0;
|
||||
Bits.unreserveMemory(size, capacity);
|
||||
}
|
||||
|
@ -124,12 +118,12 @@ class Direct$Type$Buffer$RW$$BO$
|
|||
|
||||
long base = 0;
|
||||
try {
|
||||
base = unsafe.allocateMemory(size);
|
||||
base = UNSAFE.allocateMemory(size);
|
||||
} catch (OutOfMemoryError x) {
|
||||
Bits.unreserveMemory(size, cap);
|
||||
throw x;
|
||||
}
|
||||
unsafe.setMemory(base, size, (byte) 0);
|
||||
UNSAFE.setMemory(base, size, (byte) 0);
|
||||
if (pa && (base % ps != 0)) {
|
||||
// Round up to page boundary
|
||||
address = base + ps - (base & (ps - 1));
|
||||
|
@ -206,6 +200,11 @@ class Direct$Type$Buffer$RW$$BO$
|
|||
#end[rw]
|
||||
}
|
||||
|
||||
@Override
|
||||
Object base() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public $Type$Buffer slice() {
|
||||
int pos = this.position();
|
||||
int lim = this.limit();
|
||||
|
@ -258,16 +257,16 @@ class Direct$Type$Buffer$RW$$BO$
|
|||
}
|
||||
|
||||
public $type$ get() {
|
||||
return $fromBits$($swap$(unsafe.get$Swaptype$(ix(nextGetIndex()))));
|
||||
return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(nextGetIndex()))));
|
||||
}
|
||||
|
||||
public $type$ get(int i) {
|
||||
return $fromBits$($swap$(unsafe.get$Swaptype$(ix(checkIndex(i)))));
|
||||
return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(checkIndex(i)))));
|
||||
}
|
||||
|
||||
#if[streamableType]
|
||||
$type$ getUnchecked(int i) {
|
||||
return $fromBits$($swap$(unsafe.get$Swaptype$(ix(i))));
|
||||
return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(i))));
|
||||
}
|
||||
#end[streamableType]
|
||||
|
||||
|
@ -282,10 +281,10 @@ class Direct$Type$Buffer$RW$$BO$
|
|||
if (length > rem)
|
||||
throw new BufferUnderflowException();
|
||||
|
||||
long dstOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$);
|
||||
long dstOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
|
||||
#if[!byte]
|
||||
if (order() != ByteOrder.nativeOrder())
|
||||
unsafe.copySwapMemory(null,
|
||||
UNSAFE.copySwapMemory(null,
|
||||
ix(pos),
|
||||
dst,
|
||||
dstOffset,
|
||||
|
@ -293,7 +292,7 @@ class Direct$Type$Buffer$RW$$BO$
|
|||
(long)1 << $LG_BYTES_PER_VALUE$);
|
||||
else
|
||||
#end[!byte]
|
||||
unsafe.copyMemory(null,
|
||||
UNSAFE.copyMemory(null,
|
||||
ix(pos),
|
||||
dst,
|
||||
dstOffset,
|
||||
|
@ -312,7 +311,7 @@ class Direct$Type$Buffer$RW$$BO$
|
|||
|
||||
public $Type$Buffer put($type$ x) {
|
||||
#if[rw]
|
||||
unsafe.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x)));
|
||||
UNSAFE.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x)));
|
||||
return this;
|
||||
#else[rw]
|
||||
throw new ReadOnlyBufferException();
|
||||
|
@ -321,7 +320,7 @@ class Direct$Type$Buffer$RW$$BO$
|
|||
|
||||
public $Type$Buffer put(int i, $type$ x) {
|
||||
#if[rw]
|
||||
unsafe.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x)));
|
||||
UNSAFE.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x)));
|
||||
return this;
|
||||
#else[rw]
|
||||
throw new ReadOnlyBufferException();
|
||||
|
@ -347,7 +346,7 @@ class Direct$Type$Buffer$RW$$BO$
|
|||
|
||||
if (srem > rem)
|
||||
throw new BufferOverflowException();
|
||||
unsafe.copyMemory(sb.ix(spos), ix(pos), (long)srem << $LG_BYTES_PER_VALUE$);
|
||||
UNSAFE.copyMemory(sb.ix(spos), ix(pos), (long)srem << $LG_BYTES_PER_VALUE$);
|
||||
sb.position(spos + srem);
|
||||
position(pos + srem);
|
||||
} else if (src.hb != null) {
|
||||
|
@ -380,10 +379,10 @@ class Direct$Type$Buffer$RW$$BO$
|
|||
if (length > rem)
|
||||
throw new BufferOverflowException();
|
||||
|
||||
long srcOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$);
|
||||
long srcOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
|
||||
#if[!byte]
|
||||
if (order() != ByteOrder.nativeOrder())
|
||||
unsafe.copySwapMemory(src,
|
||||
UNSAFE.copySwapMemory(src,
|
||||
srcOffset,
|
||||
null,
|
||||
ix(pos),
|
||||
|
@ -391,7 +390,7 @@ class Direct$Type$Buffer$RW$$BO$
|
|||
(long)1 << $LG_BYTES_PER_VALUE$);
|
||||
else
|
||||
#end[!byte]
|
||||
unsafe.copyMemory(src,
|
||||
UNSAFE.copyMemory(src,
|
||||
srcOffset,
|
||||
null,
|
||||
ix(pos),
|
||||
|
@ -413,7 +412,7 @@ class Direct$Type$Buffer$RW$$BO$
|
|||
assert (pos <= lim);
|
||||
int rem = (pos <= lim ? lim - pos : 0);
|
||||
|
||||
unsafe.copyMemory(ix(pos), ix(0), (long)rem << $LG_BYTES_PER_VALUE$);
|
||||
UNSAFE.copyMemory(ix(pos), ix(0), (long)rem << $LG_BYTES_PER_VALUE$);
|
||||
position(rem);
|
||||
limit(capacity());
|
||||
discardMark();
|
||||
|
@ -490,17 +489,22 @@ class Direct$Type$Buffer$RW$$BO$
|
|||
|
||||
#end[!byte]
|
||||
|
||||
#if[char]
|
||||
ByteOrder charRegionOrder() {
|
||||
return order();
|
||||
}
|
||||
#end[char]
|
||||
|
||||
|
||||
#if[byte]
|
||||
|
||||
byte _get(int i) { // package-private
|
||||
return unsafe.getByte(address + i);
|
||||
return UNSAFE.getByte(address + i);
|
||||
}
|
||||
|
||||
void _put(int i, byte b) { // package-private
|
||||
#if[rw]
|
||||
unsafe.putByte(address + i, b);
|
||||
UNSAFE.putByte(address + i, b);
|
||||
#else[rw]
|
||||
throw new ReadOnlyBufferException();
|
||||
#end[rw]
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
|
||||
package java.nio;
|
||||
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
/**
|
||||
#if[rw]
|
||||
* A read/write Heap$Type$Buffer.
|
||||
|
@ -43,6 +41,11 @@ import jdk.internal.misc.Unsafe;
|
|||
class Heap$Type$Buffer$RW$
|
||||
extends {#if[ro]?Heap}$Type$Buffer
|
||||
{
|
||||
// Cached array base offset
|
||||
private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset($type$[].class);
|
||||
|
||||
// Cached array base offset
|
||||
private static final long ARRAY_INDEX_SCALE = UNSAFE.arrayIndexScale($type$[].class);
|
||||
|
||||
// For speed these fields are actually declared in X-Buffer;
|
||||
// these declarations are here as documentation
|
||||
|
@ -53,16 +56,6 @@ class Heap$Type$Buffer$RW$
|
|||
#end[rw]
|
||||
*/
|
||||
|
||||
#if[byte]
|
||||
|
||||
// Cached unsafe-access object
|
||||
private static final Unsafe unsafe = Bits.unsafe();
|
||||
|
||||
// Cached array base offset
|
||||
private static final long arrayBaseOffset = unsafe.arrayBaseOffset($type$[].class);
|
||||
|
||||
#end[byte]
|
||||
|
||||
Heap$Type$Buffer$RW$(int cap, int lim) { // package-private
|
||||
#if[rw]
|
||||
super(-1, 0, lim, cap, new $type$[cap], 0);
|
||||
|
@ -70,13 +63,11 @@ class Heap$Type$Buffer$RW$
|
|||
hb = new $type$[cap];
|
||||
offset = 0;
|
||||
*/
|
||||
this.address = ARRAY_BASE_OFFSET;
|
||||
#else[rw]
|
||||
super(cap, lim);
|
||||
this.isReadOnly = true;
|
||||
#end[rw]
|
||||
#if[byte]
|
||||
this.address = arrayBaseOffset;
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
Heap$Type$Buffer$RW$($type$[] buf, int off, int len) { // package-private
|
||||
|
@ -86,13 +77,11 @@ class Heap$Type$Buffer$RW$
|
|||
hb = buf;
|
||||
offset = 0;
|
||||
*/
|
||||
this.address = ARRAY_BASE_OFFSET;
|
||||
#else[rw]
|
||||
super(buf, off, len);
|
||||
this.isReadOnly = true;
|
||||
#end[rw]
|
||||
#if[byte]
|
||||
this.address = arrayBaseOffset;
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
protected Heap$Type$Buffer$RW$($type$[] buf,
|
||||
|
@ -105,13 +94,11 @@ class Heap$Type$Buffer$RW$
|
|||
hb = buf;
|
||||
offset = off;
|
||||
*/
|
||||
this.address = ARRAY_BASE_OFFSET + off * ARRAY_INDEX_SCALE;
|
||||
#else[rw]
|
||||
super(buf, mark, pos, lim, cap, off);
|
||||
this.isReadOnly = true;
|
||||
#end[rw]
|
||||
#if[byte]
|
||||
this.address = arrayBaseOffset + off;
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
public $Type$Buffer slice() {
|
||||
|
@ -296,18 +283,18 @@ class Heap$Type$Buffer$RW$
|
|||
#if[rw]
|
||||
|
||||
public char getChar() {
|
||||
return unsafe.getCharUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
|
||||
return UNSAFE.getCharUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
|
||||
}
|
||||
|
||||
public char getChar(int i) {
|
||||
return unsafe.getCharUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
|
||||
return UNSAFE.getCharUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
|
||||
}
|
||||
|
||||
#end[rw]
|
||||
|
||||
public $Type$Buffer putChar(char x) {
|
||||
#if[rw]
|
||||
unsafe.putCharUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
|
||||
UNSAFE.putCharUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
|
||||
return this;
|
||||
#else[rw]
|
||||
throw new ReadOnlyBufferException();
|
||||
|
@ -316,7 +303,7 @@ class Heap$Type$Buffer$RW$
|
|||
|
||||
public $Type$Buffer putChar(int i, char x) {
|
||||
#if[rw]
|
||||
unsafe.putCharUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
|
||||
UNSAFE.putCharUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
|
||||
return this;
|
||||
#else[rw]
|
||||
throw new ReadOnlyBufferException();
|
||||
|
@ -347,18 +334,18 @@ class Heap$Type$Buffer$RW$
|
|||
#if[rw]
|
||||
|
||||
public short getShort() {
|
||||
return unsafe.getShortUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
|
||||
return UNSAFE.getShortUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
|
||||
}
|
||||
|
||||
public short getShort(int i) {
|
||||
return unsafe.getShortUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
|
||||
return UNSAFE.getShortUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
|
||||
}
|
||||
|
||||
#end[rw]
|
||||
|
||||
public $Type$Buffer putShort(short x) {
|
||||
#if[rw]
|
||||
unsafe.putShortUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
|
||||
UNSAFE.putShortUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
|
||||
return this;
|
||||
#else[rw]
|
||||
throw new ReadOnlyBufferException();
|
||||
|
@ -367,7 +354,7 @@ class Heap$Type$Buffer$RW$
|
|||
|
||||
public $Type$Buffer putShort(int i, short x) {
|
||||
#if[rw]
|
||||
unsafe.putShortUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
|
||||
UNSAFE.putShortUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
|
||||
return this;
|
||||
#else[rw]
|
||||
throw new ReadOnlyBufferException();
|
||||
|
@ -398,18 +385,18 @@ class Heap$Type$Buffer$RW$
|
|||
#if[rw]
|
||||
|
||||
public int getInt() {
|
||||
return unsafe.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
|
||||
return UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
|
||||
}
|
||||
|
||||
public int getInt(int i) {
|
||||
return unsafe.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
|
||||
return UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
|
||||
}
|
||||
|
||||
#end[rw]
|
||||
|
||||
public $Type$Buffer putInt(int x) {
|
||||
#if[rw]
|
||||
unsafe.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), x, bigEndian);
|
||||
UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), x, bigEndian);
|
||||
return this;
|
||||
#else[rw]
|
||||
throw new ReadOnlyBufferException();
|
||||
|
@ -418,7 +405,7 @@ class Heap$Type$Buffer$RW$
|
|||
|
||||
public $Type$Buffer putInt(int i, int x) {
|
||||
#if[rw]
|
||||
unsafe.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), x, bigEndian);
|
||||
UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), x, bigEndian);
|
||||
return this;
|
||||
#else[rw]
|
||||
throw new ReadOnlyBufferException();
|
||||
|
@ -449,18 +436,18 @@ class Heap$Type$Buffer$RW$
|
|||
#if[rw]
|
||||
|
||||
public long getLong() {
|
||||
return unsafe.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
|
||||
return UNSAFE.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
|
||||
}
|
||||
|
||||
public long getLong(int i) {
|
||||
return unsafe.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
|
||||
return UNSAFE.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
|
||||
}
|
||||
|
||||
#end[rw]
|
||||
|
||||
public $Type$Buffer putLong(long x) {
|
||||
#if[rw]
|
||||
unsafe.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), x, bigEndian);
|
||||
UNSAFE.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), x, bigEndian);
|
||||
return this;
|
||||
#else[rw]
|
||||
throw new ReadOnlyBufferException();
|
||||
|
@ -469,7 +456,7 @@ class Heap$Type$Buffer$RW$
|
|||
|
||||
public $Type$Buffer putLong(int i, long x) {
|
||||
#if[rw]
|
||||
unsafe.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), x, bigEndian);
|
||||
UNSAFE.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), x, bigEndian);
|
||||
return this;
|
||||
#else[rw]
|
||||
throw new ReadOnlyBufferException();
|
||||
|
@ -500,12 +487,12 @@ class Heap$Type$Buffer$RW$
|
|||
#if[rw]
|
||||
|
||||
public float getFloat() {
|
||||
int x = unsafe.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
|
||||
int x = UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
|
||||
return Float.intBitsToFloat(x);
|
||||
}
|
||||
|
||||
public float getFloat(int i) {
|
||||
int x = unsafe.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
|
||||
int x = UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
|
||||
return Float.intBitsToFloat(x);
|
||||
}
|
||||
|
||||
|
@ -514,7 +501,7 @@ class Heap$Type$Buffer$RW$
|
|||
public $Type$Buffer putFloat(float x) {
|
||||
#if[rw]
|
||||
int y = Float.floatToRawIntBits(x);
|
||||
unsafe.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), y, bigEndian);
|
||||
UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), y, bigEndian);
|
||||
return this;
|
||||
#else[rw]
|
||||
throw new ReadOnlyBufferException();
|
||||
|
@ -524,7 +511,7 @@ class Heap$Type$Buffer$RW$
|
|||
public $Type$Buffer putFloat(int i, float x) {
|
||||
#if[rw]
|
||||
int y = Float.floatToRawIntBits(x);
|
||||
unsafe.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), y, bigEndian);
|
||||
UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), y, bigEndian);
|
||||
return this;
|
||||
#else[rw]
|
||||
throw new ReadOnlyBufferException();
|
||||
|
@ -555,12 +542,12 @@ class Heap$Type$Buffer$RW$
|
|||
#if[rw]
|
||||
|
||||
public double getDouble() {
|
||||
long x = unsafe.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
|
||||
long x = UNSAFE.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
|
||||
return Double.longBitsToDouble(x);
|
||||
}
|
||||
|
||||
public double getDouble(int i) {
|
||||
long x = unsafe.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
|
||||
long x = UNSAFE.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
|
||||
return Double.longBitsToDouble(x);
|
||||
}
|
||||
|
||||
|
@ -569,7 +556,7 @@ class Heap$Type$Buffer$RW$
|
|||
public $Type$Buffer putDouble(double x) {
|
||||
#if[rw]
|
||||
long y = Double.doubleToRawLongBits(x);
|
||||
unsafe.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), y, bigEndian);
|
||||
UNSAFE.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), y, bigEndian);
|
||||
return this;
|
||||
#else[rw]
|
||||
throw new ReadOnlyBufferException();
|
||||
|
@ -579,7 +566,7 @@ class Heap$Type$Buffer$RW$
|
|||
public $Type$Buffer putDouble(int i, double x) {
|
||||
#if[rw]
|
||||
long y = Double.doubleToRawLongBits(x);
|
||||
unsafe.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), y, bigEndian);
|
||||
UNSAFE.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), y, bigEndian);
|
||||
return this;
|
||||
#else[rw]
|
||||
throw new ReadOnlyBufferException();
|
||||
|
@ -643,7 +630,11 @@ class Heap$Type$Buffer$RW$
|
|||
public ByteOrder order() {
|
||||
return ByteOrder.nativeOrder();
|
||||
}
|
||||
|
||||
#end[!byte]
|
||||
#if[char]
|
||||
|
||||
ByteOrder charRegionOrder() {
|
||||
return order();
|
||||
}
|
||||
#end[char]
|
||||
}
|
||||
|
|
|
@ -127,4 +127,30 @@ class StringCharBuffer // package-private
|
|||
return ByteOrder.nativeOrder();
|
||||
}
|
||||
|
||||
ByteOrder charRegionOrder() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean equals(Object ob) {
|
||||
if (this == ob)
|
||||
return true;
|
||||
if (!(ob instanceof CharBuffer))
|
||||
return false;
|
||||
CharBuffer that = (CharBuffer)ob;
|
||||
if (this.remaining() != that.remaining())
|
||||
return false;
|
||||
return BufferMismatch.mismatch(this, this.position(),
|
||||
that, that.position(),
|
||||
this.remaining()) < 0;
|
||||
}
|
||||
|
||||
public int compareTo(CharBuffer that) {
|
||||
int i = BufferMismatch.mismatch(this, this.position(),
|
||||
that, that.position(),
|
||||
Math.min(this.remaining(), that.remaining()));
|
||||
if (i >= 0) {
|
||||
return Character.compare(this.get(this.position() + i), that.get(this.position() + i));
|
||||
}
|
||||
return this.remaining() - that.remaining();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,8 @@ import java.util.stream.StreamSupport;
|
|||
import java.util.stream.$Streamtype$Stream;
|
||||
#end[streamableType]
|
||||
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
|
||||
/**
|
||||
* $A$ $type$ buffer.
|
||||
*
|
||||
|
@ -287,6 +289,11 @@ public abstract class $Type$Buffer
|
|||
this(mark, pos, lim, cap, null, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
Object base() {
|
||||
return hb;
|
||||
}
|
||||
|
||||
#if[byte]
|
||||
|
||||
/**
|
||||
|
@ -1297,19 +1304,9 @@ public abstract class $Type$Buffer
|
|||
$Type$Buffer that = ($Type$Buffer)ob;
|
||||
if (this.remaining() != that.remaining())
|
||||
return false;
|
||||
int p = this.position();
|
||||
for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--)
|
||||
if (!equals(this.get(i), that.get(j)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean equals($type$ x, $type$ y) {
|
||||
#if[floatingPointType]
|
||||
return (x == y) || ($Fulltype$.isNaN(x) && $Fulltype$.isNaN(y));
|
||||
#else[floatingPointType]
|
||||
return x == y;
|
||||
#end[floatingPointType]
|
||||
return BufferMismatch.mismatch(this, this.position(),
|
||||
that, that.position(),
|
||||
this.remaining()) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1336,11 +1333,11 @@ public abstract class $Type$Buffer
|
|||
* is less than, equal to, or greater than the given buffer
|
||||
*/
|
||||
public int compareTo($Type$Buffer that) {
|
||||
int n = this.position() + Math.min(this.remaining(), that.remaining());
|
||||
for (int i = this.position(), j = that.position(); i < n; i++, j++) {
|
||||
int cmp = compare(this.get(i), that.get(j));
|
||||
if (cmp != 0)
|
||||
return cmp;
|
||||
int i = BufferMismatch.mismatch(this, this.position(),
|
||||
that, that.position(),
|
||||
Math.min(this.remaining(), that.remaining()));
|
||||
if (i >= 0) {
|
||||
return compare(this.get(this.position() + i), that.get(this.position() + i));
|
||||
}
|
||||
return this.remaining() - that.remaining();
|
||||
}
|
||||
|
@ -1571,6 +1568,12 @@ public abstract class $Type$Buffer
|
|||
|
||||
#end[!byte]
|
||||
|
||||
#if[char]
|
||||
// The order or null if the buffer does not cover a memory region,
|
||||
// such as StringCharBuffer
|
||||
abstract ByteOrder charRegionOrder();
|
||||
#end[char]
|
||||
|
||||
#if[byte]
|
||||
|
||||
boolean bigEndian // package-private
|
||||
|
|
|
@ -121,7 +121,7 @@ public abstract class SelectableChannel
|
|||
// keySet, may be empty but is never null, typ. a tiny array
|
||||
// boolean isRegistered, protected by key set
|
||||
// regLock, lock object to prevent duplicate registrations
|
||||
// boolean isBlocking, protected by regLock
|
||||
// blocking mode, protected by regLock
|
||||
|
||||
/**
|
||||
* Tells whether or not this channel is currently registered with any
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2018, 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
|
||||
|
@ -26,7 +26,14 @@
|
|||
package java.nio.channels.spi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.channels.CancelledKeyException;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.ClosedSelectorException;
|
||||
import java.nio.channels.IllegalBlockingModeException;
|
||||
import java.nio.channels.IllegalSelectorException;
|
||||
import java.nio.channels.SelectableChannel;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -67,8 +74,8 @@ public abstract class AbstractSelectableChannel
|
|||
// Lock for registration and configureBlocking operations
|
||||
private final Object regLock = new Object();
|
||||
|
||||
// Blocking mode, protected by regLock
|
||||
boolean blocking = true;
|
||||
// True when non-blocking, need regLock to change;
|
||||
private volatile boolean nonBlocking;
|
||||
|
||||
/**
|
||||
* Initializes a new instance of this class.
|
||||
|
@ -197,7 +204,7 @@ public abstract class AbstractSelectableChannel
|
|||
throw new ClosedChannelException();
|
||||
if ((ops & ~validOps()) != 0)
|
||||
throw new IllegalArgumentException();
|
||||
if (blocking)
|
||||
if (isBlocking())
|
||||
throw new IllegalBlockingModeException();
|
||||
SelectionKey k = findKey(sel);
|
||||
if (k != null) {
|
||||
|
@ -264,9 +271,7 @@ public abstract class AbstractSelectableChannel
|
|||
// -- Blocking --
|
||||
|
||||
public final boolean isBlocking() {
|
||||
synchronized (regLock) {
|
||||
return blocking;
|
||||
}
|
||||
return !nonBlocking;
|
||||
}
|
||||
|
||||
public final Object blockingLock() {
|
||||
|
@ -287,12 +292,13 @@ public abstract class AbstractSelectableChannel
|
|||
synchronized (regLock) {
|
||||
if (!isOpen())
|
||||
throw new ClosedChannelException();
|
||||
if (blocking == block)
|
||||
return this;
|
||||
if (block && haveValidKeys())
|
||||
throw new IllegalBlockingModeException();
|
||||
implConfigureBlocking(block);
|
||||
blocking = block;
|
||||
boolean blocking = !nonBlocking;
|
||||
if (block != blocking) {
|
||||
if (block && haveValidKeys())
|
||||
throw new IllegalBlockingModeException();
|
||||
implConfigureBlocking(block);
|
||||
nonBlocking = !block;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -2954,22 +2954,6 @@ public final class Files {
|
|||
return newBufferedWriter(path, StandardCharsets.UTF_8, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all bytes from an input stream and writes them to an output stream.
|
||||
*/
|
||||
private static long copy(InputStream source, OutputStream sink)
|
||||
throws IOException
|
||||
{
|
||||
long nread = 0L;
|
||||
byte[] buf = new byte[BUFFER_SIZE];
|
||||
int n;
|
||||
while ((n = source.read(buf)) > 0) {
|
||||
sink.write(buf, 0, n);
|
||||
nread += n;
|
||||
}
|
||||
return nread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all bytes from an input stream to a file. On return, the input
|
||||
* stream will be at end of stream.
|
||||
|
@ -3082,7 +3066,7 @@ public final class Files {
|
|||
|
||||
// do the copy
|
||||
try (OutputStream out = ostream) {
|
||||
return copy(in, out);
|
||||
return in.transferTo(out);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3124,7 +3108,7 @@ public final class Files {
|
|||
Objects.requireNonNull(out);
|
||||
|
||||
try (InputStream in = newInputStream(source)) {
|
||||
return copy(in, out);
|
||||
return in.transferTo(out);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2018, 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
|
||||
|
@ -394,6 +394,12 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
|||
|
||||
/**
|
||||
* Gets month strings. For example: "January", "February", etc.
|
||||
* An array with either 12 or 13 elements will be returned depending
|
||||
* on whether or not {@link java.util.Calendar#UNDECIMBER Calendar.UNDECIMBER}
|
||||
* is supported. Use
|
||||
* {@link java.util.Calendar#JANUARY Calendar.JANUARY},
|
||||
* {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY},
|
||||
* etc. to index the result array.
|
||||
*
|
||||
* <p>If the language requires different forms for formatting and
|
||||
* stand-alone usages, this method returns month names in the
|
||||
|
@ -405,10 +411,9 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
|||
* Calendar Elements in the Unicode Locale Data Markup Language
|
||||
* (LDML) specification</a> for more details.
|
||||
*
|
||||
* @return the month strings. Use
|
||||
* {@link java.util.Calendar#JANUARY Calendar.JANUARY},
|
||||
* {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY},
|
||||
* etc. to index the result array.
|
||||
* @implSpec This method returns 13 elements since
|
||||
* {@link java.util.Calendar#UNDECIMBER Calendar.UNDECIMBER} is supported.
|
||||
* @return the month strings.
|
||||
*/
|
||||
public String[] getMonths() {
|
||||
return Arrays.copyOf(months, months.length);
|
||||
|
@ -427,6 +432,12 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
|||
|
||||
/**
|
||||
* Gets short month strings. For example: "Jan", "Feb", etc.
|
||||
* An array with either 12 or 13 elements will be returned depending
|
||||
* on whether or not {@link java.util.Calendar#UNDECIMBER Calendar.UNDECIMBER}
|
||||
* is supported. Use
|
||||
* {@link java.util.Calendar#JANUARY Calendar.JANUARY},
|
||||
* {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY},
|
||||
* etc. to index the result array.
|
||||
*
|
||||
* <p>If the language requires different forms for formatting and
|
||||
* stand-alone usages, this method returns short month names in
|
||||
|
@ -438,10 +449,9 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
|||
* Calendar Elements in the Unicode Locale Data Markup Language
|
||||
* (LDML) specification</a> for more details.
|
||||
*
|
||||
* @return the short month strings. Use
|
||||
* {@link java.util.Calendar#JANUARY Calendar.JANUARY},
|
||||
* {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY},
|
||||
* etc. to index the result array.
|
||||
* @implSpec This method returns 13 elements since
|
||||
* {@link java.util.Calendar#UNDECIMBER Calendar.UNDECIMBER} is supported.
|
||||
* @return the short month strings.
|
||||
*/
|
||||
public String[] getShortMonths() {
|
||||
return Arrays.copyOf(shortMonths, shortMonths.length);
|
||||
|
|
|
@ -610,7 +610,7 @@ public final class Instant
|
|||
* <p>
|
||||
* The epoch second count is a simple incrementing count of seconds where
|
||||
* second 0 is 1970-01-01T00:00:00Z.
|
||||
* The nanosecond part of the day is returned by {@link #getNano}.
|
||||
* The nanosecond part is returned by {@link #getNano}.
|
||||
*
|
||||
* @return the seconds from the epoch of 1970-01-01T00:00:00Z
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2018, 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
|
||||
|
@ -708,9 +708,8 @@ public final class IsoFields {
|
|||
return (R) temporal.with(WEEK_BASED_YEAR,
|
||||
Math.addExact(temporal.get(WEEK_BASED_YEAR), amount));
|
||||
case QUARTER_YEARS:
|
||||
// no overflow (256 is multiple of 4)
|
||||
return (R) temporal.plus(amount / 256, YEARS)
|
||||
.plus((amount % 256) * 3, MONTHS);
|
||||
return (R) temporal.plus(amount / 4, YEARS)
|
||||
.plus((amount % 4) * 3, MONTHS);
|
||||
default:
|
||||
throw new IllegalStateException("Unreachable");
|
||||
}
|
||||
|
|
|
@ -1143,6 +1143,23 @@ public class ArrayList<E> extends AbstractList<E>
|
|||
return modified;
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
checkForComodification();
|
||||
return Arrays.copyOfRange(root.elementData, offset, offset + size);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T[] toArray(T[] a) {
|
||||
checkForComodification();
|
||||
if (a.length < size)
|
||||
return (T[]) Arrays.copyOfRange(
|
||||
root.elementData, offset, offset + size, a.getClass());
|
||||
System.arraycopy(root.elementData, offset, a, 0, size);
|
||||
if (a.length > size)
|
||||
a[size] = null;
|
||||
return a;
|
||||
}
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return listIterator();
|
||||
}
|
||||
|
@ -1550,7 +1567,6 @@ public class ArrayList<E> extends AbstractList<E>
|
|||
setBit(deathRow, i - beg);
|
||||
if (modCount != expectedModCount)
|
||||
throw new ConcurrentModificationException();
|
||||
expectedModCount++;
|
||||
modCount++;
|
||||
int w = beg;
|
||||
for (i = beg; i < end; i++)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
package java.util;
|
||||
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
|
|
|
@ -116,8 +116,8 @@ public class Base64 {
|
|||
*
|
||||
* @param lineLength
|
||||
* the length of each output line (rounded down to nearest multiple
|
||||
* of 4). If {@code lineLength <= 0} the output will not be separated
|
||||
* in lines
|
||||
* of 4). If the rounded down line length is not a positive value,
|
||||
* the output will not be separated in lines
|
||||
* @param lineSeparator
|
||||
* the line separator for each output line
|
||||
*
|
||||
|
@ -135,10 +135,12 @@ public class Base64 {
|
|||
throw new IllegalArgumentException(
|
||||
"Illegal base64 line separator character 0x" + Integer.toString(b, 16));
|
||||
}
|
||||
// round down to nearest multiple of 4
|
||||
lineLength &= ~0b11;
|
||||
if (lineLength <= 0) {
|
||||
return Encoder.RFC4648;
|
||||
}
|
||||
return new Encoder(false, lineSeparator, lineLength >> 2 << 2, true);
|
||||
return new Encoder(false, lineSeparator, lineLength, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -808,17 +808,26 @@ public final class Locale implements Cloneable, Serializable {
|
|||
}
|
||||
|
||||
static Locale getInstance(BaseLocale baseloc, LocaleExtensions extensions) {
|
||||
LocaleKey key = new LocaleKey(baseloc, extensions);
|
||||
return LOCALECACHE.get(key);
|
||||
if (extensions == null) {
|
||||
return LOCALECACHE.get(baseloc);
|
||||
} else {
|
||||
LocaleKey key = new LocaleKey(baseloc, extensions);
|
||||
return LOCALECACHE.get(key);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Cache extends LocaleObjectCache<LocaleKey, Locale> {
|
||||
private static class Cache extends LocaleObjectCache<Object, Locale> {
|
||||
private Cache() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Locale createObject(LocaleKey key) {
|
||||
return new Locale(key.base, key.exts);
|
||||
protected Locale createObject(Object key) {
|
||||
if (key instanceof BaseLocale) {
|
||||
return new Locale((BaseLocale)key, null);
|
||||
} else {
|
||||
LocaleKey lk = (LocaleKey)key;
|
||||
return new Locale(lk.base, lk.exts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1023,7 +1023,6 @@ public class Vector<E>
|
|||
setBit(deathRow, i - beg);
|
||||
if (modCount != expectedModCount)
|
||||
throw new ConcurrentModificationException();
|
||||
expectedModCount++;
|
||||
modCount++;
|
||||
int w = beg;
|
||||
for (i = beg; i < end; i++)
|
||||
|
|
|
@ -245,8 +245,7 @@ public abstract class AbstractExecutorService implements ExecutorService {
|
|||
Future<T> f = futures.get(i);
|
||||
if (!f.isDone()) {
|
||||
try { f.get(); }
|
||||
catch (CancellationException ignore) {}
|
||||
catch (ExecutionException ignore) {}
|
||||
catch (CancellationException | ExecutionException ignore) {}
|
||||
}
|
||||
}
|
||||
return futures;
|
||||
|
@ -283,8 +282,7 @@ public abstract class AbstractExecutorService implements ExecutorService {
|
|||
Future<T> f = futures.get(j);
|
||||
if (!f.isDone()) {
|
||||
try { f.get(deadline - System.nanoTime(), NANOSECONDS); }
|
||||
catch (CancellationException ignore) {}
|
||||
catch (ExecutionException ignore) {}
|
||||
catch (CancellationException | ExecutionException ignore) {}
|
||||
catch (TimeoutException timedOut) {
|
||||
break timedOut;
|
||||
}
|
||||
|
|
|
@ -717,12 +717,12 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
|||
*/
|
||||
static Class<?> comparableClassFor(Object x) {
|
||||
if (x instanceof Comparable) {
|
||||
Class<?> c; Type[] ts, as; Type t; ParameterizedType p;
|
||||
Class<?> c; Type[] ts, as; ParameterizedType p;
|
||||
if ((c = x.getClass()) == String.class) // bypass checks
|
||||
return c;
|
||||
if ((ts = c.getGenericInterfaces()) != null) {
|
||||
for (int i = 0; i < ts.length; ++i) {
|
||||
if (((t = ts[i]) instanceof ParameterizedType) &&
|
||||
for (Type t : ts) {
|
||||
if ((t instanceof ParameterizedType) &&
|
||||
((p = (ParameterizedType)t).getRawType() ==
|
||||
Comparable.class) &&
|
||||
(as = p.getActualTypeArguments()) != null &&
|
||||
|
@ -2328,15 +2328,15 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
|||
* @param check if <0, don't check resize, if <= 1 only check if uncontended
|
||||
*/
|
||||
private final void addCount(long x, int check) {
|
||||
CounterCell[] as; long b, s;
|
||||
if ((as = counterCells) != null ||
|
||||
CounterCell[] cs; long b, s;
|
||||
if ((cs = counterCells) != null ||
|
||||
!U.compareAndSetLong(this, BASECOUNT, b = baseCount, s = b + x)) {
|
||||
CounterCell a; long v; int m;
|
||||
CounterCell c; long v; int m;
|
||||
boolean uncontended = true;
|
||||
if (as == null || (m = as.length - 1) < 0 ||
|
||||
(a = as[ThreadLocalRandom.getProbe() & m]) == null ||
|
||||
if (cs == null || (m = cs.length - 1) < 0 ||
|
||||
(c = cs[ThreadLocalRandom.getProbe() & m]) == null ||
|
||||
!(uncontended =
|
||||
U.compareAndSetLong(a, CELLVALUE, v = a.value, v + x))) {
|
||||
U.compareAndSetLong(c, CELLVALUE, v = c.value, v + x))) {
|
||||
fullAddCount(x, uncontended);
|
||||
return;
|
||||
}
|
||||
|
@ -2574,13 +2574,12 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
|||
}
|
||||
|
||||
final long sumCount() {
|
||||
CounterCell[] as = counterCells; CounterCell a;
|
||||
CounterCell[] cs = counterCells;
|
||||
long sum = baseCount;
|
||||
if (as != null) {
|
||||
for (int i = 0; i < as.length; ++i) {
|
||||
if ((a = as[i]) != null)
|
||||
sum += a.value;
|
||||
}
|
||||
if (cs != null) {
|
||||
for (CounterCell c : cs)
|
||||
if (c != null)
|
||||
sum += c.value;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
@ -2595,9 +2594,9 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
|||
}
|
||||
boolean collide = false; // True if last slot nonempty
|
||||
for (;;) {
|
||||
CounterCell[] as; CounterCell a; int n; long v;
|
||||
if ((as = counterCells) != null && (n = as.length) > 0) {
|
||||
if ((a = as[(n - 1) & h]) == null) {
|
||||
CounterCell[] cs; CounterCell c; int n; long v;
|
||||
if ((cs = counterCells) != null && (n = cs.length) > 0) {
|
||||
if ((c = cs[(n - 1) & h]) == null) {
|
||||
if (cellsBusy == 0) { // Try to attach new Cell
|
||||
CounterCell r = new CounterCell(x); // Optimistic create
|
||||
if (cellsBusy == 0 &&
|
||||
|
@ -2623,21 +2622,17 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
|||
}
|
||||
else if (!wasUncontended) // CAS already known to fail
|
||||
wasUncontended = true; // Continue after rehash
|
||||
else if (U.compareAndSetLong(a, CELLVALUE, v = a.value, v + x))
|
||||
else if (U.compareAndSetLong(c, CELLVALUE, v = c.value, v + x))
|
||||
break;
|
||||
else if (counterCells != as || n >= NCPU)
|
||||
else if (counterCells != cs || n >= NCPU)
|
||||
collide = false; // At max size or stale
|
||||
else if (!collide)
|
||||
collide = true;
|
||||
else if (cellsBusy == 0 &&
|
||||
U.compareAndSetInt(this, CELLSBUSY, 0, 1)) {
|
||||
try {
|
||||
if (counterCells == as) {// Expand table unless stale
|
||||
CounterCell[] rs = new CounterCell[n << 1];
|
||||
for (int i = 0; i < n; ++i)
|
||||
rs[i] = as[i];
|
||||
counterCells = rs;
|
||||
}
|
||||
if (counterCells == cs) // Expand table unless stale
|
||||
counterCells = Arrays.copyOf(cs, n << 1);
|
||||
} finally {
|
||||
cellsBusy = 0;
|
||||
}
|
||||
|
@ -2646,11 +2641,11 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
|||
}
|
||||
h = ThreadLocalRandom.advanceProbe(h);
|
||||
}
|
||||
else if (cellsBusy == 0 && counterCells == as &&
|
||||
else if (cellsBusy == 0 && counterCells == cs &&
|
||||
U.compareAndSetInt(this, CELLSBUSY, 0, 1)) {
|
||||
boolean init = false;
|
||||
try { // Initialize table
|
||||
if (counterCells == as) {
|
||||
if (counterCells == cs) {
|
||||
CounterCell[] rs = new CounterCell[2];
|
||||
rs[h & 1] = new CounterCell(x);
|
||||
counterCells = rs;
|
||||
|
|
|
@ -2204,9 +2204,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
|
|||
Collection<?> c = (Collection<?>) o;
|
||||
try {
|
||||
return containsAll(c) && c.containsAll(this);
|
||||
} catch (ClassCastException unused) {
|
||||
return false;
|
||||
} catch (NullPointerException unused) {
|
||||
} catch (ClassCastException | NullPointerException unused) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -2331,9 +2329,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
|
|||
Collection<?> c = (Collection<?>) o;
|
||||
try {
|
||||
return containsAll(c) && c.containsAll(this);
|
||||
} catch (ClassCastException unused) {
|
||||
return false;
|
||||
} catch (NullPointerException unused) {
|
||||
} catch (ClassCastException | NullPointerException unused) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -2453,9 +2449,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
|
|||
if (k == null) // pass by markers and headers
|
||||
return true;
|
||||
int c = cpr(cmp, k, hi);
|
||||
if (c > 0 || (c == 0 && !hiInclusive))
|
||||
return false;
|
||||
return true;
|
||||
return c < 0 || (c == 0 && hiInclusive);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -309,9 +309,7 @@ public class ConcurrentSkipListSet<E>
|
|||
Collection<?> c = (Collection<?>) o;
|
||||
try {
|
||||
return containsAll(c) && c.containsAll(this);
|
||||
} catch (ClassCastException unused) {
|
||||
return false;
|
||||
} catch (NullPointerException unused) {
|
||||
} catch (ClassCastException | NullPointerException unused) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -508,7 +508,7 @@ public class CopyOnWriteArrayList<E>
|
|||
public boolean remove(Object o) {
|
||||
Object[] snapshot = getArray();
|
||||
int index = indexOf(o, snapshot, 0, snapshot.length);
|
||||
return (index < 0) ? false : remove(o, snapshot, index);
|
||||
return index >= 0 && remove(o, snapshot, index);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -587,8 +587,8 @@ public class CopyOnWriteArrayList<E>
|
|||
*/
|
||||
public boolean addIfAbsent(E e) {
|
||||
Object[] snapshot = getArray();
|
||||
return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
|
||||
addIfAbsent(e, snapshot);
|
||||
return indexOf(e, snapshot, 0, snapshot.length) < 0
|
||||
&& addIfAbsent(e, snapshot);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -980,13 +980,10 @@ public class CopyOnWriteArrayList<E>
|
|||
|
||||
List<?> list = (List<?>)o;
|
||||
Iterator<?> it = list.iterator();
|
||||
Object[] elements = getArray();
|
||||
for (int i = 0, len = elements.length; i < len; i++)
|
||||
if (!it.hasNext() || !Objects.equals(elements[i], it.next()))
|
||||
for (Object element : getArray())
|
||||
if (!it.hasNext() || !Objects.equals(element, it.next()))
|
||||
return false;
|
||||
if (it.hasNext())
|
||||
return false;
|
||||
return true;
|
||||
return !it.hasNext();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1353,17 +1353,16 @@ public class LinkedBlockingDeque<E>
|
|||
@SuppressWarnings("unchecked")
|
||||
private boolean bulkRemove(Predicate<? super E> filter) {
|
||||
boolean removed = false;
|
||||
Node<E> p = null;
|
||||
final ReentrantLock lock = this.lock;
|
||||
Node<E> p = null;
|
||||
Node<E>[] nodes = null;
|
||||
int n, len = 0;
|
||||
do {
|
||||
// 1. Extract batch of up to 64 elements while holding the lock.
|
||||
long deathRow = 0; // "bitset" of size 64
|
||||
lock.lock();
|
||||
try {
|
||||
if (nodes == null) {
|
||||
if (p == null) p = first;
|
||||
if (nodes == null) { // first batch; initialize
|
||||
p = first;
|
||||
for (Node<E> q = p; q != null; q = succ(q))
|
||||
if (q.item != null && ++len == 64)
|
||||
break;
|
||||
|
@ -1376,6 +1375,7 @@ public class LinkedBlockingDeque<E>
|
|||
}
|
||||
|
||||
// 2. Run the filter on the elements while lock is free.
|
||||
long deathRow = 0L; // "bitset" of size 64
|
||||
for (int i = 0; i < n; i++) {
|
||||
final E e;
|
||||
if ((e = nodes[i].item) != null && filter.test(e))
|
||||
|
@ -1393,6 +1393,7 @@ public class LinkedBlockingDeque<E>
|
|||
unlink(q);
|
||||
removed = true;
|
||||
}
|
||||
nodes[i] = null; // help GC
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
|
|
|
@ -1060,11 +1060,10 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
|
|||
int n, len = 0;
|
||||
do {
|
||||
// 1. Extract batch of up to 64 elements while holding the lock.
|
||||
long deathRow = 0; // "bitset" of size 64
|
||||
fullyLock();
|
||||
try {
|
||||
if (nodes == null) {
|
||||
if (p == null) p = head.next;
|
||||
if (nodes == null) { // first batch; initialize
|
||||
p = head.next;
|
||||
for (Node<E> q = p; q != null; q = succ(q))
|
||||
if (q.item != null && ++len == 64)
|
||||
break;
|
||||
|
@ -1077,6 +1076,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
|
|||
}
|
||||
|
||||
// 2. Run the filter on the elements while lock is free.
|
||||
long deathRow = 0L; // "bitset" of size 64
|
||||
for (int i = 0; i < n; i++) {
|
||||
final E e;
|
||||
if ((e = nodes[i].item) != null && filter.test(e))
|
||||
|
@ -1095,6 +1095,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
|
|||
unlink(q, ancestor);
|
||||
removed = true;
|
||||
}
|
||||
nodes[i] = null; // help GC
|
||||
}
|
||||
} finally {
|
||||
fullyUnlock();
|
||||
|
|
|
@ -772,9 +772,8 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
|
|||
Node first = null;
|
||||
restartFromHead: for (;;) {
|
||||
Node h = head, p = h;
|
||||
for (; p != null;) {
|
||||
final Object item;
|
||||
if ((item = p.item) != null) {
|
||||
while (p != null) {
|
||||
if (p.item != null) {
|
||||
if (p.isData) {
|
||||
first = p;
|
||||
break;
|
||||
|
@ -1602,8 +1601,7 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
|
|||
// Read in elements until trailing null sentinel found
|
||||
Node h = null, t = null;
|
||||
for (Object item; (item = s.readObject()) != null; ) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Node newNode = new Node((E) item);
|
||||
Node newNode = new Node(item);
|
||||
if (h == null)
|
||||
h = t = newNode;
|
||||
else
|
||||
|
|
|
@ -269,8 +269,8 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
|
|||
if (a.getClass() != Object[].class)
|
||||
a = Arrays.copyOf(a, n, Object[].class);
|
||||
if (screen && (n == 1 || this.comparator != null)) {
|
||||
for (int i = 0; i < n; ++i)
|
||||
if (a[i] == null)
|
||||
for (Object elt : a)
|
||||
if (elt == null)
|
||||
throw new NullPointerException();
|
||||
}
|
||||
this.queue = a;
|
||||
|
|
|
@ -753,8 +753,10 @@ public class SubmissionPublisher<T> implements Publisher<T>,
|
|||
else
|
||||
pred.next = next;
|
||||
}
|
||||
else
|
||||
else {
|
||||
subs.add(b.subscriber);
|
||||
pred = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
return subs;
|
||||
|
|
|
@ -67,7 +67,7 @@ import jdk.internal.misc.VM;
|
|||
* {@code ThreadLocalRandom.current().nextX(...)} (where
|
||||
* {@code X} is {@code Int}, {@code Long}, etc).
|
||||
* When all usages are of this form, it is never possible to
|
||||
* accidently share a {@code ThreadLocalRandom} across multiple threads.
|
||||
* accidentally share a {@code ThreadLocalRandom} across multiple threads.
|
||||
*
|
||||
* <p>This class also provides additional commonly used bounded random
|
||||
* generation methods.
|
||||
|
|
|
@ -264,13 +264,12 @@ import java.util.concurrent.locks.ReentrantLock;
|
|||
* assist in storage reclamation when large numbers of queued tasks
|
||||
* become cancelled.</dd>
|
||||
*
|
||||
* <dt>Finalization</dt>
|
||||
* <dt>Reclamation</dt>
|
||||
*
|
||||
* <dd>A pool that is no longer referenced in a program <em>AND</em>
|
||||
* has no remaining threads will be {@code shutdown} automatically. If
|
||||
* you would like to ensure that unreferenced pools are reclaimed even
|
||||
* if users forget to call {@link #shutdown}, then you must arrange
|
||||
* that unused threads eventually die, by setting appropriate
|
||||
* has no remaining threads may be reclaimed (garbage collected)
|
||||
* without being explicity shutdown. You can configure a pool to allow
|
||||
* all unused threads to eventually die by setting appropriate
|
||||
* keep-alive times, using a lower bound of zero core threads and/or
|
||||
* setting {@link #allowCoreThreadTimeOut(boolean)}. </dd>
|
||||
*
|
||||
|
@ -361,7 +360,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
|
|||
* time, but need not hit each state. The transitions are:
|
||||
*
|
||||
* RUNNING -> SHUTDOWN
|
||||
* On invocation of shutdown(), perhaps implicitly in finalize()
|
||||
* On invocation of shutdown()
|
||||
* (RUNNING or SHUTDOWN) -> STOP
|
||||
* On invocation of shutdownNow()
|
||||
* SHUTDOWN -> TIDYING
|
||||
|
@ -581,9 +580,6 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
|
|||
private static final RuntimePermission shutdownPerm =
|
||||
new RuntimePermission("modifyThread");
|
||||
|
||||
/** The context to be used when executing the finalizer, or null. */
|
||||
private final AccessControlContext acc;
|
||||
|
||||
/**
|
||||
* Class Worker mainly maintains interrupt control state for
|
||||
* threads running tasks, along with other minor bookkeeping.
|
||||
|
@ -1300,9 +1296,6 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
|
|||
throw new IllegalArgumentException();
|
||||
if (workQueue == null || threadFactory == null || handler == null)
|
||||
throw new NullPointerException();
|
||||
this.acc = (System.getSecurityManager() == null)
|
||||
? null
|
||||
: AccessController.getContext();
|
||||
this.corePoolSize = corePoolSize;
|
||||
this.maximumPoolSize = maximumPoolSize;
|
||||
this.workQueue = workQueue;
|
||||
|
@ -1469,33 +1462,6 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes {@code shutdown} when this executor is no longer
|
||||
* referenced and it has no threads.
|
||||
*
|
||||
* <p>This method is invoked with privileges that are restricted by
|
||||
* the security context of the caller that invokes the constructor.
|
||||
*
|
||||
* @deprecated The {@code finalize} method has been deprecated.
|
||||
* Subclasses that override {@code finalize} in order to perform cleanup
|
||||
* should be modified to use alternative cleanup mechanisms and
|
||||
* to remove the overriding {@code finalize} method.
|
||||
* When overriding the {@code finalize} method, its implementation must explicitly
|
||||
* ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}.
|
||||
* See the specification for {@link Object#finalize()} for further
|
||||
* information about migration options.
|
||||
*/
|
||||
@Deprecated(since="9")
|
||||
protected void finalize() {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm == null || acc == null) {
|
||||
shutdown();
|
||||
} else {
|
||||
PrivilegedAction<Void> pa = () -> { shutdown(); return null; };
|
||||
AccessController.doPrivileged(pa, acc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the thread factory used to create new threads.
|
||||
*
|
||||
|
|
|
@ -320,7 +320,9 @@ public abstract class AbstractQueuedLongSynchronizer
|
|||
|
||||
// predNext is the apparent node to unsplice. CASes below will
|
||||
// fail if not, in which case, we lost race vs another cancel
|
||||
// or signal, so no further action is necessary.
|
||||
// or signal, so no further action is necessary, although with
|
||||
// a possibility that a cancelled node may transiently remain
|
||||
// reachable.
|
||||
Node predNext = pred.next;
|
||||
|
||||
// Can use unconditional write instead of CAS here.
|
||||
|
@ -912,13 +914,13 @@ public abstract class AbstractQueuedLongSynchronizer
|
|||
* at any time, a {@code true} return does not guarantee that any
|
||||
* other thread will ever acquire.
|
||||
*
|
||||
* <p>In this implementation, this operation returns in
|
||||
* constant time.
|
||||
*
|
||||
* @return {@code true} if there may be other threads waiting to acquire
|
||||
*/
|
||||
public final boolean hasQueuedThreads() {
|
||||
return head != tail;
|
||||
for (Node p = tail, h = head; p != h && p != null; p = p.prev)
|
||||
if (p.waitStatus <= 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1067,17 +1069,21 @@ public abstract class AbstractQueuedLongSynchronizer
|
|||
* @since 1.7
|
||||
*/
|
||||
public final boolean hasQueuedPredecessors() {
|
||||
// The correctness of this depends on head being initialized
|
||||
// before tail and on head.next being accurate if the current
|
||||
// thread is first in queue.
|
||||
Node t = tail; // Read fields in reverse initialization order
|
||||
Node h = head;
|
||||
Node s;
|
||||
return h != t &&
|
||||
((s = h.next) == null || s.thread != Thread.currentThread());
|
||||
Node h, s;
|
||||
if ((h = head) != null) {
|
||||
if ((s = h.next) == null || s.waitStatus > 0) {
|
||||
s = null; // traverse in case of concurrent cancellation
|
||||
for (Node p = tail; p != h && p != null; p = p.prev) {
|
||||
if (p.waitStatus <= 0)
|
||||
s = p;
|
||||
}
|
||||
}
|
||||
if (s != null && s.thread != Thread.currentThread())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Instrumentation and monitoring methods
|
||||
|
||||
/**
|
||||
|
|
|
@ -800,7 +800,9 @@ public abstract class AbstractQueuedSynchronizer
|
|||
|
||||
// predNext is the apparent node to unsplice. CASes below will
|
||||
// fail if not, in which case, we lost race vs another cancel
|
||||
// or signal, so no further action is necessary.
|
||||
// or signal, so no further action is necessary, although with
|
||||
// a possibility that a cancelled node may transiently remain
|
||||
// reachable.
|
||||
Node predNext = pred.next;
|
||||
|
||||
// Can use unconditional write instead of CAS here.
|
||||
|
@ -1392,13 +1394,13 @@ public abstract class AbstractQueuedSynchronizer
|
|||
* at any time, a {@code true} return does not guarantee that any
|
||||
* other thread will ever acquire.
|
||||
*
|
||||
* <p>In this implementation, this operation returns in
|
||||
* constant time.
|
||||
*
|
||||
* @return {@code true} if there may be other threads waiting to acquire
|
||||
*/
|
||||
public final boolean hasQueuedThreads() {
|
||||
return head != tail;
|
||||
for (Node p = tail, h = head; p != h && p != null; p = p.prev)
|
||||
if (p.waitStatus <= 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1547,17 +1549,21 @@ public abstract class AbstractQueuedSynchronizer
|
|||
* @since 1.7
|
||||
*/
|
||||
public final boolean hasQueuedPredecessors() {
|
||||
// The correctness of this depends on head being initialized
|
||||
// before tail and on head.next being accurate if the current
|
||||
// thread is first in queue.
|
||||
Node t = tail; // Read fields in reverse initialization order
|
||||
Node h = head;
|
||||
Node s;
|
||||
return h != t &&
|
||||
((s = h.next) == null || s.thread != Thread.currentThread());
|
||||
Node h, s;
|
||||
if ((h = head) != null) {
|
||||
if ((s = h.next) == null || s.waitStatus > 0) {
|
||||
s = null; // traverse in case of concurrent cancellation
|
||||
for (Node p = tail; p != h && p != null; p = p.prev) {
|
||||
if (p.waitStatus <= 0)
|
||||
s = p;
|
||||
}
|
||||
}
|
||||
if (s != null && s.thread != Thread.currentThread())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Instrumentation and monitoring methods
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2018, 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
|
||||
|
@ -953,6 +953,12 @@ public final class Pattern
|
|||
*/
|
||||
private int flags;
|
||||
|
||||
/**
|
||||
* The temporary pattern flags used during compiling. The flags might be turn
|
||||
* on and off by embedded flag.
|
||||
*/
|
||||
private transient int flags0;
|
||||
|
||||
/**
|
||||
* Boolean indicating this Pattern is compiled; this is necessary in order
|
||||
* to lazily compile deserialized Patterns.
|
||||
|
@ -1137,7 +1143,7 @@ public final class Pattern
|
|||
* @return The match flags specified when this pattern was compiled
|
||||
*/
|
||||
public int flags() {
|
||||
return flags;
|
||||
return flags0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1369,6 +1375,9 @@ public final class Pattern
|
|||
// Read in all fields
|
||||
s.defaultReadObject();
|
||||
|
||||
// reset the flags
|
||||
flags0 = flags;
|
||||
|
||||
// Initialize counts
|
||||
capturingGroupCount = 1;
|
||||
localCount = 0;
|
||||
|
@ -1400,6 +1409,9 @@ public final class Pattern
|
|||
if ((flags & UNICODE_CHARACTER_CLASS) != 0)
|
||||
flags |= UNICODE_CASE;
|
||||
|
||||
// 'flags' for compiling
|
||||
flags0 = flags;
|
||||
|
||||
// Reset group index count
|
||||
capturingGroupCount = 1;
|
||||
localCount = 0;
|
||||
|
@ -1841,7 +1853,7 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
|
|||
* Indicates whether a particular flag is set or not.
|
||||
*/
|
||||
private boolean has(int f) {
|
||||
return (flags & f) != 0;
|
||||
return (flags0 & f) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2718,7 +2730,7 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
|
|||
ch == 0x53 || ch == 0x73 || //S and s
|
||||
ch == 0x4b || ch == 0x6b || //K and k
|
||||
ch == 0xc5 || ch == 0xe5))) { //A+ring
|
||||
bits.add(ch, flags());
|
||||
bits.add(ch, flags0);
|
||||
return null;
|
||||
}
|
||||
return single(ch);
|
||||
|
@ -2931,7 +2943,7 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
|
|||
boolean capturingGroup = false;
|
||||
Node head = null;
|
||||
Node tail = null;
|
||||
int save = flags;
|
||||
int save = flags0;
|
||||
int saveTCNCount = topClosureNodes.size();
|
||||
root = null;
|
||||
int ch = next();
|
||||
|
@ -3032,7 +3044,7 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
|
|||
}
|
||||
|
||||
accept(')', "Unclosed group");
|
||||
flags = save;
|
||||
flags0 = save;
|
||||
|
||||
// Check for quantifiers
|
||||
Node node = closure(head);
|
||||
|
@ -3135,28 +3147,28 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
|
|||
for (;;) {
|
||||
switch (ch) {
|
||||
case 'i':
|
||||
flags |= CASE_INSENSITIVE;
|
||||
flags0 |= CASE_INSENSITIVE;
|
||||
break;
|
||||
case 'm':
|
||||
flags |= MULTILINE;
|
||||
flags0 |= MULTILINE;
|
||||
break;
|
||||
case 's':
|
||||
flags |= DOTALL;
|
||||
flags0 |= DOTALL;
|
||||
break;
|
||||
case 'd':
|
||||
flags |= UNIX_LINES;
|
||||
flags0 |= UNIX_LINES;
|
||||
break;
|
||||
case 'u':
|
||||
flags |= UNICODE_CASE;
|
||||
flags0 |= UNICODE_CASE;
|
||||
break;
|
||||
case 'c':
|
||||
flags |= CANON_EQ;
|
||||
flags0 |= CANON_EQ;
|
||||
break;
|
||||
case 'x':
|
||||
flags |= COMMENTS;
|
||||
flags0 |= COMMENTS;
|
||||
break;
|
||||
case 'U':
|
||||
flags |= (UNICODE_CHARACTER_CLASS | UNICODE_CASE);
|
||||
flags0 |= (UNICODE_CHARACTER_CLASS | UNICODE_CASE);
|
||||
break;
|
||||
case '-': // subFlag then fall through
|
||||
ch = next();
|
||||
|
@ -3178,28 +3190,28 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
|
|||
for (;;) {
|
||||
switch (ch) {
|
||||
case 'i':
|
||||
flags &= ~CASE_INSENSITIVE;
|
||||
flags0 &= ~CASE_INSENSITIVE;
|
||||
break;
|
||||
case 'm':
|
||||
flags &= ~MULTILINE;
|
||||
flags0 &= ~MULTILINE;
|
||||
break;
|
||||
case 's':
|
||||
flags &= ~DOTALL;
|
||||
flags0 &= ~DOTALL;
|
||||
break;
|
||||
case 'd':
|
||||
flags &= ~UNIX_LINES;
|
||||
flags0 &= ~UNIX_LINES;
|
||||
break;
|
||||
case 'u':
|
||||
flags &= ~UNICODE_CASE;
|
||||
flags0 &= ~UNICODE_CASE;
|
||||
break;
|
||||
case 'c':
|
||||
flags &= ~CANON_EQ;
|
||||
flags0 &= ~CANON_EQ;
|
||||
break;
|
||||
case 'x':
|
||||
flags &= ~COMMENTS;
|
||||
flags0 &= ~COMMENTS;
|
||||
break;
|
||||
case 'U':
|
||||
flags &= ~(UNICODE_CHARACTER_CLASS | UNICODE_CASE);
|
||||
flags0 &= ~(UNICODE_CHARACTER_CLASS | UNICODE_CASE);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -27,6 +27,8 @@ package jdk.internal.misc;
|
|||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
|
||||
import jdk.internal.ref.PhantomCleanable;
|
||||
|
||||
/*
|
||||
* @author Chris Hegarty
|
||||
*/
|
||||
|
@ -38,6 +40,8 @@ public interface JavaIOFileDescriptorAccess {
|
|||
public boolean getAppend(FileDescriptor fdo);
|
||||
public void close(FileDescriptor fdo) throws IOException;
|
||||
public void registerCleanup(FileDescriptor fdo);
|
||||
public void registerCleanup(FileDescriptor fdo, PhantomCleanable<Object> cleanable);
|
||||
public void unregisterCleanup(FileDescriptor fdo);
|
||||
|
||||
// Only valid on Windows
|
||||
public void setHandle(FileDescriptor fdo, long handle);
|
||||
|
|
|
@ -64,7 +64,7 @@ import static jdk.internal.module.ClassFileConstants.*;
|
|||
public final class ModuleInfo {
|
||||
|
||||
private final int JAVA_MIN_SUPPORTED_VERSION = 53;
|
||||
private final int JAVA_MAX_SUPPORTED_VERSION = 54;
|
||||
private final int JAVA_MAX_SUPPORTED_VERSION = 55;
|
||||
|
||||
private static final JavaLangModuleAccess JLMA
|
||||
= SharedSecrets.getJavaLangModuleAccess();
|
||||
|
|
|
@ -185,7 +185,7 @@ public class ClassReader {
|
|||
public ClassReader(final byte[] b, final int off, final int len) {
|
||||
this.b = b;
|
||||
// checks the class version
|
||||
if (readShort(off + 6) > Opcodes.V10) {
|
||||
if (readShort(off + 6) > Opcodes.V11) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
// parses the constant pool
|
||||
|
|
|
@ -90,6 +90,7 @@ public interface Opcodes {
|
|||
int V1_8 = 0 << 16 | 52;
|
||||
int V9 = 0 << 16 | 53;
|
||||
int V10 = 0 << 16 | 54;
|
||||
int V11 = 0 << 16 | 55;
|
||||
|
||||
// access flags
|
||||
|
||||
|
|
|
@ -64,14 +64,6 @@ public class Reflection {
|
|||
@HotSpotIntrinsicCandidate
|
||||
public static native Class<?> getCallerClass();
|
||||
|
||||
/**
|
||||
* @deprecated This method will be removed.
|
||||
* This method is a private JDK API and retained temporarily to
|
||||
* simplify the implementation of sun.misc.Reflection.getCallerClass.
|
||||
*/
|
||||
@Deprecated(forRemoval=true)
|
||||
public static native Class<?> getCallerClass(int depth);
|
||||
|
||||
/** Retrieves the access flags written to the class file. For
|
||||
inner classes these flags may differ from those returned by
|
||||
Class.getModifiers(), which searches the InnerClasses
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2017 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
|
||||
|
@ -22,7 +22,7 @@
|
|||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.util;
|
||||
package jdk.internal.util;
|
||||
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
@ -50,19 +50,19 @@ import jdk.internal.misc.Unsafe;
|
|||
* responsibility of the caller (direct or otherwise) to perform such checks
|
||||
* before calling this method.
|
||||
*/
|
||||
class ArraysSupport {
|
||||
public class ArraysSupport {
|
||||
static final Unsafe U = Unsafe.getUnsafe();
|
||||
|
||||
private static final boolean BIG_ENDIAN = U.isBigEndian();
|
||||
|
||||
private static final int LOG2_ARRAY_BOOLEAN_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BOOLEAN_INDEX_SCALE);
|
||||
private static final int LOG2_ARRAY_BYTE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BYTE_INDEX_SCALE);
|
||||
private static final int LOG2_ARRAY_CHAR_INDEX_SCALE = exactLog2(Unsafe.ARRAY_CHAR_INDEX_SCALE);
|
||||
private static final int LOG2_ARRAY_SHORT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_SHORT_INDEX_SCALE);
|
||||
private static final int LOG2_ARRAY_INT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_INT_INDEX_SCALE);
|
||||
private static final int LOG2_ARRAY_LONG_INDEX_SCALE = exactLog2(Unsafe.ARRAY_LONG_INDEX_SCALE);
|
||||
private static final int LOG2_ARRAY_FLOAT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_FLOAT_INDEX_SCALE);
|
||||
private static final int LOG2_ARRAY_DOUBLE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
|
||||
public static final int LOG2_ARRAY_BOOLEAN_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BOOLEAN_INDEX_SCALE);
|
||||
public static final int LOG2_ARRAY_BYTE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BYTE_INDEX_SCALE);
|
||||
public static final int LOG2_ARRAY_CHAR_INDEX_SCALE = exactLog2(Unsafe.ARRAY_CHAR_INDEX_SCALE);
|
||||
public static final int LOG2_ARRAY_SHORT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_SHORT_INDEX_SCALE);
|
||||
public static final int LOG2_ARRAY_INT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_INT_INDEX_SCALE);
|
||||
public static final int LOG2_ARRAY_LONG_INDEX_SCALE = exactLog2(Unsafe.ARRAY_LONG_INDEX_SCALE);
|
||||
public static final int LOG2_ARRAY_FLOAT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_FLOAT_INDEX_SCALE);
|
||||
public static final int LOG2_ARRAY_DOUBLE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
|
||||
|
||||
private static final int LOG2_BYTE_BIT_SIZE = exactLog2(Byte.SIZE);
|
||||
|
||||
|
@ -107,10 +107,10 @@ class ArraysSupport {
|
|||
* the tail of the two arrays.
|
||||
*/
|
||||
@HotSpotIntrinsicCandidate
|
||||
static int vectorizedMismatch(Object a, long aOffset,
|
||||
Object b, long bOffset,
|
||||
int length,
|
||||
int log2ArrayIndexScale) {
|
||||
public static int vectorizedMismatch(Object a, long aOffset,
|
||||
Object b, long bOffset,
|
||||
int length,
|
||||
int log2ArrayIndexScale) {
|
||||
// assert a.getClass().isArray();
|
||||
// assert b.getClass().isArray();
|
||||
// assert 0 <= length <= sizeOf(a)
|
||||
|
@ -161,9 +161,9 @@ class ArraysSupport {
|
|||
// Booleans
|
||||
// Each boolean element takes up one byte
|
||||
|
||||
static int mismatch(boolean[] a,
|
||||
boolean[] b,
|
||||
int length) {
|
||||
public static int mismatch(boolean[] a,
|
||||
boolean[] b,
|
||||
int length) {
|
||||
int i = 0;
|
||||
if (length > 7) {
|
||||
i = vectorizedMismatch(
|
||||
|
@ -181,9 +181,9 @@ class ArraysSupport {
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int mismatch(boolean[] a, int aFromIndex,
|
||||
boolean[] b, int bFromIndex,
|
||||
int length) {
|
||||
public static int mismatch(boolean[] a, int aFromIndex,
|
||||
boolean[] b, int bFromIndex,
|
||||
int length) {
|
||||
int i = 0;
|
||||
if (length > 7) {
|
||||
int aOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET + aFromIndex;
|
||||
|
@ -219,9 +219,9 @@ class ArraysSupport {
|
|||
* no mismatch. The index will be within the range of (inclusive) 0 to
|
||||
* (exclusive) the smaller of the two array lengths.
|
||||
*/
|
||||
static int mismatch(byte[] a,
|
||||
byte[] b,
|
||||
int length) {
|
||||
public static int mismatch(byte[] a,
|
||||
byte[] b,
|
||||
int length) {
|
||||
// ISSUE: defer to index receiving methods if performance is good
|
||||
// assert length <= a.length
|
||||
// assert length <= b.length
|
||||
|
@ -264,9 +264,9 @@ class ArraysSupport {
|
|||
* otherwise -1 if no mismatch. The index will be within the range of
|
||||
* (inclusive) 0 to (exclusive) the smaller of the two array bounds.
|
||||
*/
|
||||
static int mismatch(byte[] a, int aFromIndex,
|
||||
byte[] b, int bFromIndex,
|
||||
int length) {
|
||||
public static int mismatch(byte[] a, int aFromIndex,
|
||||
byte[] b, int bFromIndex,
|
||||
int length) {
|
||||
// assert 0 <= aFromIndex < a.length
|
||||
// assert 0 <= aFromIndex + length <= a.length
|
||||
// assert 0 <= bFromIndex < b.length
|
||||
|
@ -295,9 +295,9 @@ class ArraysSupport {
|
|||
|
||||
// Chars
|
||||
|
||||
static int mismatch(char[] a,
|
||||
char[] b,
|
||||
int length) {
|
||||
public static int mismatch(char[] a,
|
||||
char[] b,
|
||||
int length) {
|
||||
int i = 0;
|
||||
if (length > 3) {
|
||||
i = vectorizedMismatch(
|
||||
|
@ -315,9 +315,9 @@ class ArraysSupport {
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int mismatch(char[] a, int aFromIndex,
|
||||
char[] b, int bFromIndex,
|
||||
int length) {
|
||||
public static int mismatch(char[] a, int aFromIndex,
|
||||
char[] b, int bFromIndex,
|
||||
int length) {
|
||||
int i = 0;
|
||||
if (length > 3) {
|
||||
int aOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_CHAR_INDEX_SCALE);
|
||||
|
@ -340,9 +340,9 @@ class ArraysSupport {
|
|||
|
||||
// Shorts
|
||||
|
||||
static int mismatch(short[] a,
|
||||
short[] b,
|
||||
int length) {
|
||||
public static int mismatch(short[] a,
|
||||
short[] b,
|
||||
int length) {
|
||||
int i = 0;
|
||||
if (length > 3) {
|
||||
i = vectorizedMismatch(
|
||||
|
@ -360,9 +360,9 @@ class ArraysSupport {
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int mismatch(short[] a, int aFromIndex,
|
||||
short[] b, int bFromIndex,
|
||||
int length) {
|
||||
public static int mismatch(short[] a, int aFromIndex,
|
||||
short[] b, int bFromIndex,
|
||||
int length) {
|
||||
int i = 0;
|
||||
if (length > 3) {
|
||||
int aOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_SHORT_INDEX_SCALE);
|
||||
|
@ -385,9 +385,9 @@ class ArraysSupport {
|
|||
|
||||
// Ints
|
||||
|
||||
static int mismatch(int[] a,
|
||||
int[] b,
|
||||
int length) {
|
||||
public static int mismatch(int[] a,
|
||||
int[] b,
|
||||
int length) {
|
||||
int i = 0;
|
||||
if (length > 1) {
|
||||
i = vectorizedMismatch(
|
||||
|
@ -405,9 +405,9 @@ class ArraysSupport {
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int mismatch(int[] a, int aFromIndex,
|
||||
int[] b, int bFromIndex,
|
||||
int length) {
|
||||
public static int mismatch(int[] a, int aFromIndex,
|
||||
int[] b, int bFromIndex,
|
||||
int length) {
|
||||
int i = 0;
|
||||
if (length > 1) {
|
||||
int aOffset = Unsafe.ARRAY_INT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_INT_INDEX_SCALE);
|
||||
|
@ -430,15 +430,15 @@ class ArraysSupport {
|
|||
|
||||
// Floats
|
||||
|
||||
static int mismatch(float[] a,
|
||||
float[] b,
|
||||
int length) {
|
||||
public static int mismatch(float[] a,
|
||||
float[] b,
|
||||
int length) {
|
||||
return mismatch(a, 0, b, 0, length);
|
||||
}
|
||||
|
||||
static int mismatch(float[] a, int aFromIndex,
|
||||
float[] b, int bFromIndex,
|
||||
int length) {
|
||||
public static int mismatch(float[] a, int aFromIndex,
|
||||
float[] b, int bFromIndex,
|
||||
int length) {
|
||||
int i = 0;
|
||||
if (length > 1) {
|
||||
int aOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_FLOAT_INDEX_SCALE);
|
||||
|
@ -475,9 +475,9 @@ class ArraysSupport {
|
|||
|
||||
// Long
|
||||
|
||||
static int mismatch(long[] a,
|
||||
long[] b,
|
||||
int length) {
|
||||
public static int mismatch(long[] a,
|
||||
long[] b,
|
||||
int length) {
|
||||
if (length == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -488,9 +488,9 @@ class ArraysSupport {
|
|||
return i >= 0 ? i : -1;
|
||||
}
|
||||
|
||||
static int mismatch(long[] a, int aFromIndex,
|
||||
long[] b, int bFromIndex,
|
||||
int length) {
|
||||
public static int mismatch(long[] a, int aFromIndex,
|
||||
long[] b, int bFromIndex,
|
||||
int length) {
|
||||
if (length == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -506,15 +506,15 @@ class ArraysSupport {
|
|||
|
||||
// Double
|
||||
|
||||
static int mismatch(double[] a,
|
||||
double[] b,
|
||||
int length) {
|
||||
public static int mismatch(double[] a,
|
||||
double[] b,
|
||||
int length) {
|
||||
return mismatch(a, 0, b, 0, length);
|
||||
}
|
||||
|
||||
static int mismatch(double[] a, int aFromIndex,
|
||||
double[] b, int bFromIndex,
|
||||
int length) {
|
||||
public static int mismatch(double[] a, int aFromIndex,
|
||||
double[] b, int bFromIndex,
|
||||
int length) {
|
||||
if (length == 0) {
|
||||
return -1;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2018, 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
|
||||
|
@ -142,7 +142,7 @@ module java.base {
|
|||
java.instrument,
|
||||
java.logging;
|
||||
exports jdk.internal.jmod to
|
||||
jdk.compiler, // reflective dependency
|
||||
jdk.compiler,
|
||||
jdk.jlink;
|
||||
exports jdk.internal.logger to
|
||||
java.logging;
|
||||
|
@ -172,7 +172,7 @@ module java.base {
|
|||
java.xml,
|
||||
jdk.attach,
|
||||
jdk.charsets,
|
||||
jdk.compiler, // reflective dependency
|
||||
jdk.compiler,
|
||||
jdk.incubator.httpclient,
|
||||
jdk.jdeps,
|
||||
jdk.jlink,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2018, 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
|
||||
|
@ -136,7 +136,7 @@ abstract class AsynchronousFileChannelImpl
|
|||
if (fileLockTable == null) {
|
||||
synchronized (this) {
|
||||
if (fileLockTable == null) {
|
||||
fileLockTable = FileLockTable.newSharedFileLockTable(this, fdObj);
|
||||
fileLockTable = new FileLockTable(this, fdObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -27,11 +27,32 @@ package sun.nio.ch;
|
|||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.PortUnreachableException;
|
||||
import java.net.ProtocolFamily;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketOption;
|
||||
import java.net.StandardProtocolFamily;
|
||||
import java.net.StandardSocketOptions;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.channels.spi.*;
|
||||
import java.util.*;
|
||||
import java.nio.channels.AlreadyBoundException;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.nio.channels.MembershipKey;
|
||||
import java.nio.channels.NotYetConnectedException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.UnsupportedAddressTypeException;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import sun.net.ResourceManager;
|
||||
import sun.net.ext.ExtendedSocketOptions;
|
||||
|
||||
|
@ -49,9 +70,6 @@ class DatagramChannelImpl
|
|||
|
||||
// Our file descriptor
|
||||
private final FileDescriptor fd;
|
||||
|
||||
// fd value needed for dev/poll. This value will remain valid
|
||||
// even after the value in the file descriptor object has been set to -1
|
||||
private final int fdVal;
|
||||
|
||||
// The protocol family of the socket
|
||||
|
@ -67,10 +85,10 @@ class DatagramChannelImpl
|
|||
private int cachedSenderPort;
|
||||
|
||||
// Lock held by current reading or connecting thread
|
||||
private final Object readLock = new Object();
|
||||
private final ReentrantLock readLock = new ReentrantLock();
|
||||
|
||||
// Lock held by current writing or connecting thread
|
||||
private final Object writeLock = new Object();
|
||||
private final ReentrantLock writeLock = new ReentrantLock();
|
||||
|
||||
// Lock held by any thread that modifies the state fields declared below
|
||||
// DO NOT invoke a blocking I/O operation while holding this lock!
|
||||
|
@ -103,7 +121,6 @@ class DatagramChannelImpl
|
|||
|
||||
// -- End of fields protected by stateLock
|
||||
|
||||
|
||||
public DatagramChannelImpl(SelectorProvider sp)
|
||||
throws IOException
|
||||
{
|
||||
|
@ -138,16 +155,27 @@ class DatagramChannelImpl
|
|||
throw new UnsupportedOperationException("IPv6 not available");
|
||||
}
|
||||
}
|
||||
this.family = family;
|
||||
this.fd = Net.socket(family, false);
|
||||
this.fdVal = IOUtil.fdVal(fd);
|
||||
this.state = ST_UNCONNECTED;
|
||||
|
||||
ResourceManager.beforeUdpCreate();
|
||||
try {
|
||||
this.family = family;
|
||||
this.fd = Net.socket(family, false);
|
||||
this.fdVal = IOUtil.fdVal(fd);
|
||||
this.state = ST_UNCONNECTED;
|
||||
} catch (IOException ioe) {
|
||||
ResourceManager.afterUdpClose();
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
|
||||
public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd)
|
||||
throws IOException
|
||||
{
|
||||
super(sp);
|
||||
|
||||
// increment UDP count to match decrement when closing
|
||||
ResourceManager.beforeUdpCreate();
|
||||
|
||||
this.family = Net.isIPv6Available() ?
|
||||
StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
|
||||
this.fd = fd;
|
||||
|
@ -328,7 +356,8 @@ class DatagramChannelImpl
|
|||
public SocketAddress receive(ByteBuffer dst) throws IOException {
|
||||
if (dst.isReadOnly())
|
||||
throw new IllegalArgumentException("Read-only buffer");
|
||||
synchronized (readLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
ensureOpen();
|
||||
// Socket was not bound before attempting receive
|
||||
if (localAddress() == null)
|
||||
|
@ -348,6 +377,8 @@ class DatagramChannelImpl
|
|||
if (n == IOStatus.UNAVAILABLE)
|
||||
return null;
|
||||
} else {
|
||||
// Cannot receive into user's buffer when running with a
|
||||
// security manager and not connected
|
||||
bb = Util.getTemporaryDirectBuffer(dst.remaining());
|
||||
for (;;) {
|
||||
do {
|
||||
|
@ -379,6 +410,8 @@ class DatagramChannelImpl
|
|||
end((n > 0) || (n == IOStatus.UNAVAILABLE));
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -425,7 +458,8 @@ class DatagramChannelImpl
|
|||
if (src == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
synchronized (writeLock) {
|
||||
writeLock.lock();
|
||||
try {
|
||||
ensureOpen();
|
||||
InetSocketAddress isa = Net.checkAddress(target);
|
||||
InetAddress ia = isa.getAddress();
|
||||
|
@ -474,6 +508,8 @@ class DatagramChannelImpl
|
|||
end((n > 0) || (n == IOStatus.UNAVAILABLE));
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -534,7 +570,8 @@ class DatagramChannelImpl
|
|||
public int read(ByteBuffer buf) throws IOException {
|
||||
if (buf == null)
|
||||
throw new NullPointerException();
|
||||
synchronized (readLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
ensureOpen();
|
||||
if (!isConnected())
|
||||
|
@ -555,6 +592,8 @@ class DatagramChannelImpl
|
|||
end((n > 0) || (n == IOStatus.UNAVAILABLE));
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -563,7 +602,8 @@ class DatagramChannelImpl
|
|||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
synchronized (readLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
ensureOpen();
|
||||
if (!isConnected())
|
||||
|
@ -584,13 +624,16 @@ class DatagramChannelImpl
|
|||
end((n > 0) || (n == IOStatus.UNAVAILABLE));
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int write(ByteBuffer buf) throws IOException {
|
||||
if (buf == null)
|
||||
throw new NullPointerException();
|
||||
synchronized (writeLock) {
|
||||
writeLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
ensureOpen();
|
||||
if (!isConnected())
|
||||
|
@ -611,6 +654,8 @@ class DatagramChannelImpl
|
|||
end((n > 0) || (n == IOStatus.UNAVAILABLE));
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -619,7 +664,8 @@ class DatagramChannelImpl
|
|||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
synchronized (writeLock) {
|
||||
writeLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
ensureOpen();
|
||||
if (!isConnected())
|
||||
|
@ -640,6 +686,8 @@ class DatagramChannelImpl
|
|||
end((n > 0) || (n == IOStatus.UNAVAILABLE));
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -661,8 +709,10 @@ class DatagramChannelImpl
|
|||
|
||||
@Override
|
||||
public DatagramChannel bind(SocketAddress local) throws IOException {
|
||||
synchronized (readLock) {
|
||||
synchronized (writeLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
writeLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
ensureOpen();
|
||||
if (localAddress != null)
|
||||
|
@ -692,7 +742,11 @@ class DatagramChannelImpl
|
|||
Net.bind(family, fd, isa.getAddress(), isa.getPort());
|
||||
localAddress = Net.localAddress(fd);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -714,8 +768,10 @@ class DatagramChannelImpl
|
|||
|
||||
@Override
|
||||
public DatagramChannel connect(SocketAddress sa) throws IOException {
|
||||
synchronized(readLock) {
|
||||
synchronized(writeLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
writeLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
ensureOpenAndUnconnected();
|
||||
InetSocketAddress isa = Net.checkAddress(sa);
|
||||
|
@ -741,10 +797,9 @@ class DatagramChannelImpl
|
|||
localAddress = Net.localAddress(fd);
|
||||
|
||||
// flush any packets already received.
|
||||
boolean blocking = false;
|
||||
synchronized (blockingLock()) {
|
||||
boolean blocking = isBlocking();
|
||||
try {
|
||||
blocking = isBlocking();
|
||||
ByteBuffer tmpBuf = ByteBuffer.allocate(100);
|
||||
if (blocking) {
|
||||
configureBlocking(false);
|
||||
|
@ -759,14 +814,20 @@ class DatagramChannelImpl
|
|||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public DatagramChannel disconnect() throws IOException {
|
||||
synchronized(readLock) {
|
||||
synchronized(writeLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
writeLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
if (!isConnected() || !isOpen())
|
||||
return this;
|
||||
|
@ -783,7 +844,11 @@ class DatagramChannelImpl
|
|||
// refresh local address
|
||||
localAddress = Net.localAddress(fd);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -1087,7 +1152,8 @@ class DatagramChannelImpl
|
|||
int poll(int events, long timeout) throws IOException {
|
||||
assert Thread.holdsLock(blockingLock()) && !isBlocking();
|
||||
|
||||
synchronized (readLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
int n = 0;
|
||||
try {
|
||||
begin();
|
||||
|
@ -1102,6 +1168,8 @@ class DatagramChannelImpl
|
|||
end(n > 0);
|
||||
}
|
||||
return n;
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2018, 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
|
||||
|
@ -25,10 +25,22 @@
|
|||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.DatagramSocketImpl;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketOption;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.StandardSocketOptions;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.nio.channels.IllegalBlockingModeException;
|
||||
|
||||
|
||||
// Make a datagram-socket channel look like a datagram socket.
|
||||
|
@ -178,7 +190,6 @@ public class DatagramSocketAdaptor
|
|||
|
||||
dc.configureBlocking(false);
|
||||
try {
|
||||
int n;
|
||||
SocketAddress sender;
|
||||
if ((sender = dc.receive(bb)) != null)
|
||||
return sender;
|
||||
|
@ -188,19 +199,18 @@ public class DatagramSocketAdaptor
|
|||
throw new ClosedChannelException();
|
||||
long st = System.currentTimeMillis();
|
||||
int result = dc.poll(Net.POLLIN, to);
|
||||
if (result > 0 &&
|
||||
((result & Net.POLLIN) != 0)) {
|
||||
if (result > 0 && ((result & Net.POLLIN) != 0)) {
|
||||
if ((sender = dc.receive(bb)) != null)
|
||||
return sender;
|
||||
}
|
||||
to -= System.currentTimeMillis() - st;
|
||||
if (to <= 0)
|
||||
throw new SocketTimeoutException();
|
||||
|
||||
}
|
||||
} finally {
|
||||
if (dc.isOpen())
|
||||
try {
|
||||
dc.configureBlocking(true);
|
||||
} catch (ClosedChannelException e) { }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2018, 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
|
||||
|
@ -1083,49 +1083,19 @@ public class FileChannelImpl
|
|||
|
||||
// -- Locks --
|
||||
|
||||
|
||||
|
||||
// keeps track of locks on this file
|
||||
private volatile FileLockTable fileLockTable;
|
||||
|
||||
// indicates if file locks are maintained system-wide (as per spec)
|
||||
private static boolean isSharedFileLockTable;
|
||||
|
||||
// indicates if the disableSystemWideOverlappingFileLockCheck property
|
||||
// has been checked
|
||||
private static volatile boolean propertyChecked;
|
||||
|
||||
// The lock list in J2SE 1.4/5.0 was local to each FileChannel instance so
|
||||
// the overlap check wasn't system wide when there were multiple channels to
|
||||
// the same file. This property is used to get 1.4/5.0 behavior if desired.
|
||||
private static boolean isSharedFileLockTable() {
|
||||
if (!propertyChecked) {
|
||||
synchronized (FileChannelImpl.class) {
|
||||
if (!propertyChecked) {
|
||||
String value = GetPropertyAction.privilegedGetProperty(
|
||||
"sun.nio.ch.disableSystemWideOverlappingFileLockCheck");
|
||||
isSharedFileLockTable = ((value == null) || value.equals("false"));
|
||||
propertyChecked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return isSharedFileLockTable;
|
||||
}
|
||||
|
||||
private FileLockTable fileLockTable() throws IOException {
|
||||
if (fileLockTable == null) {
|
||||
synchronized (this) {
|
||||
if (fileLockTable == null) {
|
||||
if (isSharedFileLockTable()) {
|
||||
int ti = threads.add();
|
||||
try {
|
||||
ensureOpen();
|
||||
fileLockTable = FileLockTable.newSharedFileLockTable(this, fd);
|
||||
} finally {
|
||||
threads.remove(ti);
|
||||
}
|
||||
} else {
|
||||
fileLockTable = new SimpleFileLockTable();
|
||||
int ti = threads.add();
|
||||
try {
|
||||
ensureOpen();
|
||||
fileLockTable = new FileLockTable(this, fd);
|
||||
} finally {
|
||||
threads.remove(ti);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1229,59 +1199,6 @@ public class FileChannelImpl
|
|||
fileLockTable.remove(fli);
|
||||
}
|
||||
|
||||
// -- File lock support --
|
||||
|
||||
/**
|
||||
* A simple file lock table that maintains a list of FileLocks obtained by a
|
||||
* FileChannel. Use to get 1.4/5.0 behaviour.
|
||||
*/
|
||||
private static class SimpleFileLockTable extends FileLockTable {
|
||||
// synchronize on list for access
|
||||
private final List<FileLock> lockList = new ArrayList<FileLock>(2);
|
||||
|
||||
public SimpleFileLockTable() {
|
||||
}
|
||||
|
||||
private void checkList(long position, long size)
|
||||
throws OverlappingFileLockException
|
||||
{
|
||||
assert Thread.holdsLock(lockList);
|
||||
for (FileLock fl: lockList) {
|
||||
if (fl.overlaps(position, size)) {
|
||||
throw new OverlappingFileLockException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void add(FileLock fl) throws OverlappingFileLockException {
|
||||
synchronized (lockList) {
|
||||
checkList(fl.position(), fl.size());
|
||||
lockList.add(fl);
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(FileLock fl) {
|
||||
synchronized (lockList) {
|
||||
lockList.remove(fl);
|
||||
}
|
||||
}
|
||||
|
||||
public List<FileLock> removeAll() {
|
||||
synchronized(lockList) {
|
||||
List<FileLock> result = new ArrayList<FileLock>(lockList);
|
||||
lockList.clear();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public void replace(FileLock fl1, FileLock fl2) {
|
||||
synchronized (lockList) {
|
||||
lockList.remove(fl1);
|
||||
lockList.add(fl2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -- Native methods --
|
||||
|
||||
// Creates a new mapping
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2018, 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
|
||||
|
@ -25,64 +25,27 @@
|
|||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.nio.channels.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.lang.ref.*;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
|
||||
abstract class FileLockTable {
|
||||
protected FileLockTable() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a file lock table for a channel that is connected to
|
||||
* the a system-wide map of all file locks for the Java virtual machine.
|
||||
*/
|
||||
public static FileLockTable newSharedFileLockTable(Channel channel,
|
||||
FileDescriptor fd)
|
||||
throws IOException
|
||||
{
|
||||
return new SharedFileLockTable(channel, fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a file lock to the table.
|
||||
*
|
||||
* @throws OverlappingFileLockException if the file lock overlaps
|
||||
* with an existing file lock in the table
|
||||
*/
|
||||
public abstract void add(FileLock fl) throws OverlappingFileLockException;
|
||||
|
||||
/**
|
||||
* Remove an existing file lock from the table.
|
||||
*/
|
||||
public abstract void remove(FileLock fl);
|
||||
|
||||
/**
|
||||
* Removes all file locks from the table.
|
||||
*
|
||||
* @return The list of file locks removed
|
||||
*/
|
||||
public abstract List<FileLock> removeAll();
|
||||
|
||||
/**
|
||||
* Replaces an existing file lock in the table.
|
||||
*/
|
||||
public abstract void replace(FileLock fl1, FileLock fl2);
|
||||
}
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.nio.channels.Channel;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.nio.channels.OverlappingFileLockException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* A file lock table that is over a system-wide map of all file locks.
|
||||
*/
|
||||
class SharedFileLockTable extends FileLockTable {
|
||||
|
||||
class FileLockTable {
|
||||
/**
|
||||
* A weak reference to a FileLock.
|
||||
* <p>
|
||||
* SharedFileLockTable uses a list of file lock references to avoid keeping the
|
||||
* FileLockTable uses a list of file lock references to avoid keeping the
|
||||
* FileLock (and FileChannel) alive.
|
||||
*/
|
||||
private static class FileLockReference extends WeakReference<FileLock> {
|
||||
|
@ -115,13 +78,20 @@ class SharedFileLockTable extends FileLockTable {
|
|||
// File key for the file that this channel is connected to
|
||||
private final FileKey fileKey;
|
||||
|
||||
SharedFileLockTable(Channel channel, FileDescriptor fd) throws IOException {
|
||||
// Locks obtained for this channel
|
||||
private final Set<FileLock> locks;
|
||||
|
||||
/**
|
||||
* Creates a file lock table for a channel that is connected to the
|
||||
* system-wide map of all file locks for the Java virtual machine.
|
||||
*/
|
||||
FileLockTable(Channel channel, FileDescriptor fd) throws IOException {
|
||||
this.channel = channel;
|
||||
this.fileKey = FileKey.create(fd);
|
||||
this.locks = new HashSet<FileLock>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(FileLock fl) throws OverlappingFileLockException {
|
||||
void add(FileLock fl) throws OverlappingFileLockException {
|
||||
List<FileLockReference> list = lockMap.get(fileKey);
|
||||
|
||||
for (;;) {
|
||||
|
@ -135,6 +105,7 @@ class SharedFileLockTable extends FileLockTable {
|
|||
if (prev == null) {
|
||||
// we successfully created the key so we add the file lock
|
||||
list.add(new FileLockReference(fl, queue, fileKey));
|
||||
locks.add(fl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -151,6 +122,7 @@ class SharedFileLockTable extends FileLockTable {
|
|||
if (list == current) {
|
||||
checkList(list, fl.position(), fl.size());
|
||||
list.add(new FileLockReference(fl, queue, fileKey));
|
||||
locks.add(fl);
|
||||
break;
|
||||
}
|
||||
list = current;
|
||||
|
@ -170,8 +142,7 @@ class SharedFileLockTable extends FileLockTable {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(FileLock fl) {
|
||||
void remove(FileLock fl) {
|
||||
assert fl != null;
|
||||
|
||||
// the lock must exist so the list of locks must be present
|
||||
|
@ -187,6 +158,7 @@ class SharedFileLockTable extends FileLockTable {
|
|||
assert (lock != null) && (lock.acquiredBy() == channel);
|
||||
ref.clear();
|
||||
list.remove(index);
|
||||
locks.remove(fl);
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
|
@ -194,8 +166,7 @@ class SharedFileLockTable extends FileLockTable {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FileLock> removeAll() {
|
||||
List<FileLock> removeAll() {
|
||||
List<FileLock> result = new ArrayList<FileLock>();
|
||||
List<FileLockReference> list = lockMap.get(fileKey);
|
||||
if (list != null) {
|
||||
|
@ -220,13 +191,14 @@ class SharedFileLockTable extends FileLockTable {
|
|||
|
||||
// once the lock list is empty we remove it from the map
|
||||
removeKeyIfEmpty(fileKey, list);
|
||||
|
||||
locks.clear();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replace(FileLock fromLock, FileLock toLock) {
|
||||
void replace(FileLock fromLock, FileLock toLock) {
|
||||
// the lock must exist so there must be a list
|
||||
List<FileLockReference> list = lockMap.get(fileKey);
|
||||
assert list != null;
|
||||
|
@ -238,6 +210,8 @@ class SharedFileLockTable extends FileLockTable {
|
|||
if (lock == fromLock) {
|
||||
ref.clear();
|
||||
list.set(index, new FileLockReference(toLock, queue, fileKey));
|
||||
locks.remove(fromLock);
|
||||
locks.add(toLock);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2018, 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
|
||||
|
@ -78,7 +78,7 @@ public class IOUtil {
|
|||
src.position(pos);
|
||||
|
||||
int n = writeFromNativeBuffer(fd, bb, position,
|
||||
directIO, alignment, nd);
|
||||
directIO, alignment, nd);
|
||||
if (n > 0) {
|
||||
// now update src
|
||||
src.position(pos + n);
|
||||
|
@ -161,8 +161,7 @@ public class IOUtil {
|
|||
if (!(buf instanceof DirectBuffer)) {
|
||||
ByteBuffer shadow;
|
||||
if (directIO)
|
||||
shadow = Util.getTemporaryAlignedDirectBuffer(rem,
|
||||
alignment);
|
||||
shadow = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
|
||||
else
|
||||
shadow = Util.getTemporaryDirectBuffer(rem);
|
||||
shadow.put(buf);
|
||||
|
@ -241,8 +240,7 @@ public class IOUtil {
|
|||
int rem = dst.remaining();
|
||||
if (directIO) {
|
||||
Util.checkRemainingBufferSizeAligned(rem, alignment);
|
||||
bb = Util.getTemporaryAlignedDirectBuffer(rem,
|
||||
alignment);
|
||||
bb = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
|
||||
} else {
|
||||
bb = Util.getTemporaryDirectBuffer(rem);
|
||||
}
|
||||
|
@ -277,8 +275,7 @@ public class IOUtil {
|
|||
return 0;
|
||||
int n = 0;
|
||||
if (position != -1) {
|
||||
n = nd.pread(fd, ((DirectBuffer)bb).address() + pos,
|
||||
rem, position);
|
||||
n = nd.pread(fd, ((DirectBuffer)bb).address() + pos, rem, position);
|
||||
} else {
|
||||
n = nd.read(fd, ((DirectBuffer)bb).address() + pos, rem);
|
||||
}
|
||||
|
@ -332,8 +329,7 @@ public class IOUtil {
|
|||
if (!(buf instanceof DirectBuffer)) {
|
||||
ByteBuffer shadow;
|
||||
if (directIO) {
|
||||
shadow = Util.getTemporaryAlignedDirectBuffer(rem,
|
||||
alignment);
|
||||
shadow = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
|
||||
} else {
|
||||
shadow = Util.getTemporaryDirectBuffer(rem);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2018, 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
|
||||
|
@ -25,9 +25,20 @@
|
|||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.channels.*;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.StandardSocketOptions;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.IllegalBlockingModeException;
|
||||
import java.nio.channels.NotYetBoundException;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
|
||||
// Make a server-socket channel look like a server socket.
|
||||
|
@ -37,7 +48,7 @@ import java.nio.channels.*;
|
|||
// class.
|
||||
//
|
||||
|
||||
public class ServerSocketAdaptor // package-private
|
||||
class ServerSocketAdaptor // package-private
|
||||
extends ServerSocket
|
||||
{
|
||||
|
||||
|
@ -96,13 +107,18 @@ public class ServerSocketAdaptor // package-private
|
|||
try {
|
||||
if (!ssc.isBound())
|
||||
throw new NotYetBoundException();
|
||||
|
||||
if (timeout == 0) {
|
||||
// for compatibility reasons: accept connection if available
|
||||
// when configured non-blocking
|
||||
SocketChannel sc = ssc.accept();
|
||||
if (sc == null && !ssc.isBlocking())
|
||||
throw new IllegalBlockingModeException();
|
||||
return sc.socket();
|
||||
}
|
||||
|
||||
if (!ssc.isBlocking())
|
||||
throw new IllegalBlockingModeException();
|
||||
ssc.configureBlocking(false);
|
||||
try {
|
||||
SocketChannel sc;
|
||||
|
@ -121,10 +137,10 @@ public class ServerSocketAdaptor // package-private
|
|||
throw new SocketTimeoutException();
|
||||
}
|
||||
} finally {
|
||||
if (ssc.isOpen())
|
||||
try {
|
||||
ssc.configureBlocking(true);
|
||||
} catch (ClosedChannelException e) { }
|
||||
}
|
||||
|
||||
} catch (Exception x) {
|
||||
Net.translateException(x);
|
||||
assert false;
|
||||
|
@ -178,8 +194,7 @@ public class ServerSocketAdaptor // package-private
|
|||
if (!isBound())
|
||||
return "ServerSocket[unbound]";
|
||||
return "ServerSocket[addr=" + getInetAddress() +
|
||||
// ",port=" + getPort() +
|
||||
",localport=" + getLocalPort() + "]";
|
||||
",localport=" + getLocalPort() + "]";
|
||||
}
|
||||
|
||||
public void setReceiveBufferSize(int size) throws SocketException {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -27,10 +27,25 @@ package sun.nio.ch;
|
|||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.channels.spi.*;
|
||||
import java.util.*;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ProtocolFamily;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketOption;
|
||||
import java.net.StandardProtocolFamily;
|
||||
import java.net.StandardSocketOptions;
|
||||
import java.nio.channels.AlreadyBoundException;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.NotYetBoundException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import sun.net.NetHooks;
|
||||
|
||||
/**
|
||||
|
@ -47,16 +62,13 @@ class ServerSocketChannelImpl
|
|||
|
||||
// Our file descriptor
|
||||
private final FileDescriptor fd;
|
||||
|
||||
// fd value needed for dev/poll. This value will remain valid
|
||||
// even after the value in the file descriptor object has been set to -1
|
||||
private int fdVal;
|
||||
private final int fdVal;
|
||||
|
||||
// ID of native thread currently blocked in this channel, for signalling
|
||||
private volatile long thread;
|
||||
|
||||
// Lock held by thread currently blocked in this channel
|
||||
private final Object lock = new Object();
|
||||
private final ReentrantLock acceptLock = new ReentrantLock();
|
||||
|
||||
// Lock held by any thread that modifies the state fields declared below
|
||||
// DO NOT invoke a blocking I/O operation while holding this lock!
|
||||
|
@ -77,7 +89,7 @@ class ServerSocketChannelImpl
|
|||
private boolean isReuseAddress;
|
||||
|
||||
// Our socket adaptor, if any
|
||||
ServerSocket socket;
|
||||
private ServerSocket socket;
|
||||
|
||||
// -- End of fields protected by stateLock
|
||||
|
||||
|
@ -211,7 +223,8 @@ class ServerSocketChannelImpl
|
|||
|
||||
@Override
|
||||
public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
|
||||
synchronized (lock) {
|
||||
acceptLock.lock();
|
||||
try {
|
||||
if (!isOpen())
|
||||
throw new ClosedChannelException();
|
||||
if (isBound())
|
||||
|
@ -227,12 +240,15 @@ class ServerSocketChannelImpl
|
|||
synchronized (stateLock) {
|
||||
localAddress = Net.localAddress(fd);
|
||||
}
|
||||
} finally {
|
||||
acceptLock.unlock();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public SocketChannel accept() throws IOException {
|
||||
synchronized (lock) {
|
||||
acceptLock.lock();
|
||||
try {
|
||||
if (!isOpen())
|
||||
throw new ClosedChannelException();
|
||||
if (!isBound())
|
||||
|
@ -278,6 +294,8 @@ class ServerSocketChannelImpl
|
|||
}
|
||||
return sc;
|
||||
|
||||
} finally {
|
||||
acceptLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -353,7 +371,8 @@ class ServerSocketChannelImpl
|
|||
int poll(int events, long timeout) throws IOException {
|
||||
assert Thread.holdsLock(blockingLock()) && !isBlocking();
|
||||
|
||||
synchronized (lock) {
|
||||
acceptLock.lock();
|
||||
try {
|
||||
int n = 0;
|
||||
try {
|
||||
begin();
|
||||
|
@ -368,6 +387,8 @@ class ServerSocketChannelImpl
|
|||
end(n > 0);
|
||||
}
|
||||
return n;
|
||||
} finally {
|
||||
acceptLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2018, 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
|
||||
|
@ -25,10 +25,23 @@
|
|||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketImpl;
|
||||
import java.net.SocketOption;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.StandardSocketOptions;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.IllegalBlockingModeException;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -45,7 +58,7 @@ import java.util.concurrent.TimeUnit;
|
|||
// java.net.Socket so as to simplify tracking future changes to that class.
|
||||
//
|
||||
|
||||
public class SocketAdaptor
|
||||
class SocketAdaptor
|
||||
extends Socket
|
||||
{
|
||||
|
||||
|
@ -89,7 +102,6 @@ public class SocketAdaptor
|
|||
throw new IllegalBlockingModeException();
|
||||
|
||||
try {
|
||||
|
||||
if (timeout == 0) {
|
||||
sc.connect(remote);
|
||||
return;
|
||||
|
@ -119,8 +131,9 @@ public class SocketAdaptor
|
|||
}
|
||||
}
|
||||
} finally {
|
||||
if (sc.isOpen())
|
||||
try {
|
||||
sc.configureBlocking(true);
|
||||
} catch (ClosedChannelException e) { }
|
||||
}
|
||||
|
||||
} catch (Exception x) {
|
||||
|
@ -188,10 +201,11 @@ public class SocketAdaptor
|
|||
synchronized (sc.blockingLock()) {
|
||||
if (!sc.isBlocking())
|
||||
throw new IllegalBlockingModeException();
|
||||
|
||||
if (timeout == 0)
|
||||
return sc.read(bb);
|
||||
sc.configureBlocking(false);
|
||||
|
||||
sc.configureBlocking(false);
|
||||
try {
|
||||
int n;
|
||||
if ((n = sc.read(bb)) != 0)
|
||||
|
@ -213,10 +227,10 @@ public class SocketAdaptor
|
|||
throw new SocketTimeoutException();
|
||||
}
|
||||
} finally {
|
||||
if (sc.isOpen())
|
||||
try {
|
||||
sc.configureBlocking(true);
|
||||
} catch (ClosedChannelException e) { }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -27,11 +27,30 @@ package sun.nio.ch;
|
|||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ProtocolFamily;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketOption;
|
||||
import java.net.StandardProtocolFamily;
|
||||
import java.net.StandardSocketOptions;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.channels.spi.*;
|
||||
import java.util.*;
|
||||
import java.nio.channels.AlreadyBoundException;
|
||||
import java.nio.channels.AlreadyConnectedException;
|
||||
import java.nio.channels.AsynchronousCloseException;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.ConnectionPendingException;
|
||||
import java.nio.channels.NoConnectionPendingException;
|
||||
import java.nio.channels.NotYetConnectedException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import sun.net.NetHooks;
|
||||
import sun.net.ext.ExtendedSocketOptions;
|
||||
|
||||
|
@ -49,9 +68,6 @@ class SocketChannelImpl
|
|||
|
||||
// Our file descriptor object
|
||||
private final FileDescriptor fd;
|
||||
|
||||
// fd value needed for dev/poll. This value will remain valid
|
||||
// even after the value in the file descriptor object has been set to -1
|
||||
private final int fdVal;
|
||||
|
||||
// IDs of native threads doing reads and writes, for signalling
|
||||
|
@ -59,10 +75,10 @@ class SocketChannelImpl
|
|||
private volatile long writerThread;
|
||||
|
||||
// Lock held by current reading or connecting thread
|
||||
private final Object readLock = new Object();
|
||||
private final ReentrantLock readLock = new ReentrantLock();
|
||||
|
||||
// Lock held by current writing or connecting thread
|
||||
private final Object writeLock = new Object();
|
||||
private final ReentrantLock writeLock = new ReentrantLock();
|
||||
|
||||
// Lock held by any thread that modifies the state fields declared below
|
||||
// DO NOT invoke a blocking I/O operation while holding this lock!
|
||||
|
@ -89,7 +105,6 @@ class SocketChannelImpl
|
|||
// Input/Output open
|
||||
private boolean isInputOpen = true;
|
||||
private boolean isOutputOpen = true;
|
||||
private boolean readyToConnect = false;
|
||||
|
||||
// Socket adaptor, created on demand
|
||||
private Socket socket;
|
||||
|
@ -298,7 +313,8 @@ class SocketChannelImpl
|
|||
if (buf == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
synchronized (readLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
if (!ensureReadOpen())
|
||||
return -1;
|
||||
int n = 0;
|
||||
|
@ -418,6 +434,8 @@ class SocketChannelImpl
|
|||
assert IOStatus.check(n);
|
||||
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -426,7 +444,8 @@ class SocketChannelImpl
|
|||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
synchronized (readLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
if (!ensureReadOpen())
|
||||
return -1;
|
||||
long n = 0;
|
||||
|
@ -453,13 +472,16 @@ class SocketChannelImpl
|
|||
}
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int write(ByteBuffer buf) throws IOException {
|
||||
if (buf == null)
|
||||
throw new NullPointerException();
|
||||
synchronized (writeLock) {
|
||||
writeLock.lock();
|
||||
try {
|
||||
ensureWriteOpen();
|
||||
int n = 0;
|
||||
try {
|
||||
|
@ -484,6 +506,8 @@ class SocketChannelImpl
|
|||
}
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -492,7 +516,8 @@ class SocketChannelImpl
|
|||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
synchronized (writeLock) {
|
||||
writeLock.lock();
|
||||
try {
|
||||
ensureWriteOpen();
|
||||
long n = 0;
|
||||
try {
|
||||
|
@ -517,12 +542,15 @@ class SocketChannelImpl
|
|||
}
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// package-private
|
||||
int sendOutOfBandData(byte b) throws IOException {
|
||||
synchronized (writeLock) {
|
||||
writeLock.lock();
|
||||
try {
|
||||
ensureWriteOpen();
|
||||
int n = 0;
|
||||
try {
|
||||
|
@ -547,6 +575,8 @@ class SocketChannelImpl
|
|||
}
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -568,8 +598,10 @@ class SocketChannelImpl
|
|||
|
||||
@Override
|
||||
public SocketChannel bind(SocketAddress local) throws IOException {
|
||||
synchronized (readLock) {
|
||||
synchronized (writeLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
writeLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
if (!isOpen())
|
||||
throw new ClosedChannelException();
|
||||
|
@ -587,7 +619,11 @@ class SocketChannelImpl
|
|||
Net.bind(fd, isa.getAddress(), isa.getPort());
|
||||
localAddress = Net.localAddress(fd);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -616,14 +652,16 @@ class SocketChannelImpl
|
|||
}
|
||||
|
||||
public boolean connect(SocketAddress sa) throws IOException {
|
||||
synchronized (readLock) {
|
||||
synchronized (writeLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
writeLock.lock();
|
||||
try {
|
||||
ensureOpenAndUnconnected();
|
||||
InetSocketAddress isa = Net.checkAddress(sa);
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null)
|
||||
sm.checkConnect(isa.getAddress().getHostAddress(),
|
||||
isa.getPort());
|
||||
isa.getPort());
|
||||
synchronized (blockingLock()) {
|
||||
int n = 0;
|
||||
try {
|
||||
|
@ -636,8 +674,8 @@ class SocketChannelImpl
|
|||
// notify hook only if unbound
|
||||
if (localAddress == null) {
|
||||
NetHooks.beforeTcpConnect(fd,
|
||||
isa.getAddress(),
|
||||
isa.getPort());
|
||||
isa.getAddress(),
|
||||
isa.getPort());
|
||||
}
|
||||
readerThread = NativeThread.current();
|
||||
}
|
||||
|
@ -646,10 +684,9 @@ class SocketChannelImpl
|
|||
if (ia.isAnyLocalAddress())
|
||||
ia = InetAddress.getLocalHost();
|
||||
n = Net.connect(fd,
|
||||
ia,
|
||||
isa.getPort());
|
||||
if ( (n == IOStatus.INTERRUPTED)
|
||||
&& isOpen())
|
||||
ia,
|
||||
isa.getPort());
|
||||
if ((n == IOStatus.INTERRUPTED) && isOpen())
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
@ -686,13 +723,19 @@ class SocketChannelImpl
|
|||
}
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean finishConnect() throws IOException {
|
||||
synchronized (readLock) {
|
||||
synchronized (writeLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
writeLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
if (!isOpen())
|
||||
throw new ClosedChannelException();
|
||||
|
@ -714,24 +757,20 @@ class SocketChannelImpl
|
|||
}
|
||||
if (!isBlocking()) {
|
||||
for (;;) {
|
||||
n = checkConnect(fd, false,
|
||||
readyToConnect);
|
||||
if ( (n == IOStatus.INTERRUPTED)
|
||||
&& isOpen())
|
||||
n = checkConnect(fd, false);
|
||||
if ((n == IOStatus.INTERRUPTED) && isOpen())
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for (;;) {
|
||||
n = checkConnect(fd, true,
|
||||
readyToConnect);
|
||||
n = checkConnect(fd, true);
|
||||
if (n == 0) {
|
||||
// Loop in case of
|
||||
// spurious notifications
|
||||
continue;
|
||||
}
|
||||
if ( (n == IOStatus.INTERRUPTED)
|
||||
&& isOpen())
|
||||
if ((n == IOStatus.INTERRUPTED) && isOpen())
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
@ -769,7 +808,11 @@ class SocketChannelImpl
|
|||
return true;
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -903,9 +946,6 @@ class SocketChannelImpl
|
|||
if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
|
||||
newOps = intOps;
|
||||
sk.nioReadyOps(newOps);
|
||||
// No need to poll again in checkConnect,
|
||||
// the error will be detected there
|
||||
readyToConnect = true;
|
||||
return (newOps & ~oldOps) != 0;
|
||||
}
|
||||
|
||||
|
@ -918,7 +958,6 @@ class SocketChannelImpl
|
|||
((intOps & SelectionKey.OP_CONNECT) != 0) &&
|
||||
((state == ST_UNCONNECTED) || (state == ST_PENDING))) {
|
||||
newOps |= SelectionKey.OP_CONNECT;
|
||||
readyToConnect = true;
|
||||
}
|
||||
|
||||
if (((ops & Net.POLLOUT) != 0) &&
|
||||
|
@ -942,7 +981,8 @@ class SocketChannelImpl
|
|||
int poll(int events, long timeout) throws IOException {
|
||||
assert Thread.holdsLock(blockingLock()) && !isBlocking();
|
||||
|
||||
synchronized (readLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
int n = 0;
|
||||
try {
|
||||
begin();
|
||||
|
@ -957,6 +997,8 @@ class SocketChannelImpl
|
|||
end(n > 0);
|
||||
}
|
||||
return n;
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1024,8 +1066,7 @@ class SocketChannelImpl
|
|||
|
||||
// -- Native methods --
|
||||
|
||||
private static native int checkConnect(FileDescriptor fd,
|
||||
boolean block, boolean ready)
|
||||
private static native int checkConnect(FileDescriptor fd, boolean block)
|
||||
throws IOException;
|
||||
|
||||
private static native int sendOutOfBandData(FileDescriptor fd, byte data)
|
||||
|
|
|
@ -236,10 +236,8 @@ public class DoubleByte {
|
|||
int b2 = src[sp++] & 0xff;
|
||||
if (b2 < b2Min || b2 > b2Max ||
|
||||
(c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING) {
|
||||
if (b2c[b1] == B2C_UNMAPPABLE || // isNotLeadingByte
|
||||
b2c[b2] != B2C_UNMAPPABLE || // isLeadingByte
|
||||
decodeSingle(b2) != UNMAPPABLE_DECODING) {
|
||||
sp--;
|
||||
if (crMalformedOrUnmappable(b1, b2).length() == 1) {
|
||||
sp--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -472,6 +470,13 @@ public class DoubleByte {
|
|||
b2cSB_UNMAPPABLE = new char[0x100];
|
||||
Arrays.fill(b2cSB_UNMAPPABLE, UNMAPPABLE_DECODING);
|
||||
}
|
||||
|
||||
// always returns unmappableForLenth(2) for doublebyte_only
|
||||
@Override
|
||||
protected CoderResult crMalformedOrUnmappable(int b1, int b2) {
|
||||
return CoderResult.unmappableForLength(2);
|
||||
}
|
||||
|
||||
public Decoder_DBCSONLY(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max,
|
||||
boolean isASCIICompatible) {
|
||||
super(cs, 0.5f, 1.0f, b2c, b2cSB_UNMAPPABLE, b2Min, b2Max, isASCIICompatible);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2018, 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
|
||||
|
@ -580,8 +580,8 @@ public class PolicyFile extends java.security.Policy {
|
|||
k.add(policy);
|
||||
return k;
|
||||
});
|
||||
Object[] source = {policy, pe.getLocalizedMessage()};
|
||||
System.err.println(LocalizedMessage.getMessage
|
||||
Object[] source = {policy, pe.getNonlocalizedMessage()};
|
||||
System.err.println(LocalizedMessage.getNonlocalized
|
||||
(POLICY + ".error.parsing.policy.message", source));
|
||||
if (debug != null) {
|
||||
pe.printStackTrace();
|
||||
|
@ -808,14 +808,14 @@ public class PolicyFile extends java.security.Policy {
|
|||
Object[] source = {pe.permission,
|
||||
ite.getTargetException().toString()};
|
||||
System.err.println(
|
||||
LocalizedMessage.getMessage(
|
||||
LocalizedMessage.getNonlocalized(
|
||||
POLICY + ".error.adding.Permission.perm.message",
|
||||
source));
|
||||
} catch (Exception e) {
|
||||
Object[] source = {pe.permission,
|
||||
e.toString()};
|
||||
System.err.println(
|
||||
LocalizedMessage.getMessage(
|
||||
LocalizedMessage.getNonlocalized(
|
||||
POLICY + ".error.adding.Permission.perm.message",
|
||||
source));
|
||||
}
|
||||
|
@ -826,7 +826,7 @@ public class PolicyFile extends java.security.Policy {
|
|||
} catch (Exception e) {
|
||||
Object[] source = {e.toString()};
|
||||
System.err.println(
|
||||
LocalizedMessage.getMessage(
|
||||
LocalizedMessage.getNonlocalized(
|
||||
POLICY + ".error.adding.Entry.message",
|
||||
source));
|
||||
}
|
||||
|
@ -1803,7 +1803,7 @@ public class PolicyFile extends java.security.Policy {
|
|||
if (colonIndex == -1) {
|
||||
Object[] source = {pe.name};
|
||||
throw new Exception(
|
||||
LocalizedMessage.getMessage(
|
||||
LocalizedMessage.getNonlocalized(
|
||||
"alias.name.not.provided.pe.name.",
|
||||
source));
|
||||
}
|
||||
|
@ -1811,7 +1811,7 @@ public class PolicyFile extends java.security.Policy {
|
|||
if ((suffix = getDN(suffix, keystore)) == null) {
|
||||
Object[] source = {value.substring(colonIndex+1)};
|
||||
throw new Exception(
|
||||
LocalizedMessage.getMessage(
|
||||
LocalizedMessage.getNonlocalized(
|
||||
"unable.to.perform.substitution.on.alias.suffix",
|
||||
source));
|
||||
}
|
||||
|
@ -1821,7 +1821,7 @@ public class PolicyFile extends java.security.Policy {
|
|||
} else {
|
||||
Object[] source = {prefix};
|
||||
throw new Exception(
|
||||
LocalizedMessage.getMessage(
|
||||
LocalizedMessage.getNonlocalized(
|
||||
"substitution.value.prefix.unsupported",
|
||||
source));
|
||||
}
|
||||
|
@ -2037,7 +2037,7 @@ public class PolicyFile extends java.security.Policy {
|
|||
super(type);
|
||||
if (type == null) {
|
||||
throw new NullPointerException
|
||||
(LocalizedMessage.getMessage("type.can.t.be.null"));
|
||||
(LocalizedMessage.getNonlocalized("type.can.t.be.null"));
|
||||
}
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2018, 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
|
||||
|
@ -205,8 +205,8 @@ public class PolicyParser {
|
|||
if (!domainEntries.containsKey(domainName)) {
|
||||
domainEntries.put(domainName, de);
|
||||
} else {
|
||||
LocalizedMessage localizedMsg =
|
||||
new LocalizedMessage("duplicate.keystore.domain.name");
|
||||
LocalizedMessage localizedMsg = new LocalizedMessage(
|
||||
"duplicate.keystore.domain.name");
|
||||
Object[] source = {domainName};
|
||||
String msg = "duplicate keystore domain name: " +
|
||||
domainName;
|
||||
|
@ -220,7 +220,7 @@ public class PolicyParser {
|
|||
}
|
||||
|
||||
if (keyStoreUrlString == null && storePassURL != null) {
|
||||
throw new ParsingException(LocalizedMessage.getMessage
|
||||
throw new ParsingException(LocalizedMessage.getNonlocalized
|
||||
("keystorePasswordURL.can.not.be.specified.without.also.specifying.keystore"));
|
||||
}
|
||||
}
|
||||
|
@ -362,7 +362,7 @@ public class PolicyParser {
|
|||
keyStoreType = match("quoted string");
|
||||
} else {
|
||||
throw new ParsingException(st.lineno(),
|
||||
LocalizedMessage.getMessage("expected.keystore.type"));
|
||||
LocalizedMessage.getNonlocalized("expected.keystore.type"));
|
||||
}
|
||||
|
||||
// parse keystore provider
|
||||
|
@ -375,7 +375,7 @@ public class PolicyParser {
|
|||
keyStoreProvider = match("quoted string");
|
||||
} else {
|
||||
throw new ParsingException(st.lineno(),
|
||||
LocalizedMessage.getMessage("expected.keystore.provider"));
|
||||
LocalizedMessage.getNonlocalized("expected.keystore.provider"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -425,7 +425,7 @@ public class PolicyParser {
|
|||
if (e.codeBase != null)
|
||||
throw new ParsingException(
|
||||
st.lineno(),
|
||||
LocalizedMessage.getMessage
|
||||
LocalizedMessage.getNonlocalized
|
||||
("multiple.Codebase.expressions"));
|
||||
e.codeBase = match("quoted string");
|
||||
peekAndMatch(",");
|
||||
|
@ -433,7 +433,7 @@ public class PolicyParser {
|
|||
if (e.signedBy != null)
|
||||
throw new ParsingException(
|
||||
st.lineno(),
|
||||
LocalizedMessage.getMessage
|
||||
LocalizedMessage.getNonlocalized
|
||||
("multiple.SignedBy.expressions"));
|
||||
e.signedBy = match("quoted string");
|
||||
|
||||
|
@ -452,7 +452,7 @@ public class PolicyParser {
|
|||
if (actr <= cctr)
|
||||
throw new ParsingException(
|
||||
st.lineno(),
|
||||
LocalizedMessage.getMessage
|
||||
LocalizedMessage.getNonlocalized
|
||||
("SignedBy.has.empty.alias"));
|
||||
|
||||
peekAndMatch(",");
|
||||
|
@ -495,7 +495,7 @@ public class PolicyParser {
|
|||
}
|
||||
throw new ParsingException
|
||||
(st.lineno(),
|
||||
LocalizedMessage.getMessage
|
||||
LocalizedMessage.getNonlocalized
|
||||
("can.not.specify.Principal.with.a.wildcard.class.without.a.wildcard.name"));
|
||||
}
|
||||
}
|
||||
|
@ -532,7 +532,7 @@ public class PolicyParser {
|
|||
|
||||
} else {
|
||||
throw new ParsingException(st.lineno(),
|
||||
LocalizedMessage.getMessage
|
||||
LocalizedMessage.getNonlocalized
|
||||
("expected.codeBase.or.SignedBy.or.Principal"));
|
||||
}
|
||||
}
|
||||
|
@ -556,7 +556,7 @@ public class PolicyParser {
|
|||
} else {
|
||||
throw new
|
||||
ParsingException(st.lineno(),
|
||||
LocalizedMessage.getMessage
|
||||
LocalizedMessage.getNonlocalized
|
||||
("expected.permission.entry"));
|
||||
}
|
||||
}
|
||||
|
@ -733,7 +733,7 @@ public class PolicyParser {
|
|||
switch (lookahead) {
|
||||
case StreamTokenizer.TT_NUMBER:
|
||||
throw new ParsingException(st.lineno(), expect,
|
||||
LocalizedMessage.getMessage("number.") +
|
||||
LocalizedMessage.getNonlocalized("number.") +
|
||||
String.valueOf(st.nval));
|
||||
case StreamTokenizer.TT_EOF:
|
||||
LocalizedMessage localizedMsg = new LocalizedMessage
|
||||
|
@ -826,10 +826,10 @@ public class PolicyParser {
|
|||
switch (lookahead) {
|
||||
case StreamTokenizer.TT_NUMBER:
|
||||
throw new ParsingException(st.lineno(), ";",
|
||||
LocalizedMessage.getMessage("number.") +
|
||||
LocalizedMessage.getNonlocalized("number.") +
|
||||
String.valueOf(st.nval));
|
||||
case StreamTokenizer.TT_EOF:
|
||||
throw new ParsingException(LocalizedMessage.getMessage
|
||||
throw new ParsingException(LocalizedMessage.getNonlocalized
|
||||
("expected.read.end.of.file."));
|
||||
default:
|
||||
lookahead = st.nextToken();
|
||||
|
@ -987,7 +987,7 @@ public class PolicyParser {
|
|||
*/
|
||||
public PrincipalEntry(String principalClass, String principalName) {
|
||||
if (principalClass == null || principalName == null)
|
||||
throw new NullPointerException(LocalizedMessage.getMessage
|
||||
throw new NullPointerException(LocalizedMessage.getNonlocalized
|
||||
("null.principalClass.or.principalName"));
|
||||
this.principalClass = principalClass;
|
||||
this.principalName = principalName;
|
||||
|
@ -1339,8 +1339,6 @@ public class PolicyParser {
|
|||
|
||||
public ParsingException(int line, String msg) {
|
||||
super("line " + line + ": " + msg);
|
||||
// don't call form.format unless getLocalizedMessage is called
|
||||
// to avoid unnecessary permission checks
|
||||
localizedMsg = new LocalizedMessage("line.number.msg");
|
||||
source = new Object[] {line, msg};
|
||||
}
|
||||
|
@ -1348,16 +1346,14 @@ public class PolicyParser {
|
|||
public ParsingException(int line, String expect, String actual) {
|
||||
super("line " + line + ": expected [" + expect +
|
||||
"], found [" + actual + "]");
|
||||
// don't call form.format unless getLocalizedMessage is called
|
||||
// to avoid unnecessary permission checks
|
||||
localizedMsg = new LocalizedMessage
|
||||
("line.number.expected.expect.found.actual.");
|
||||
source = new Object[] {line, expect, actual};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocalizedMessage() {
|
||||
return i18nMessage != null ? i18nMessage : localizedMsg.format(source);
|
||||
public String getNonlocalizedMessage() {
|
||||
return i18nMessage != null ? i18nMessage :
|
||||
localizedMsg.formatNonlocalized(source);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2018, 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
|
||||
|
@ -523,9 +523,11 @@ public final class Main {
|
|||
|
||||
if (c != null) {
|
||||
command = c;
|
||||
} else if (collator.compare(flags, "-help") == 0 ||
|
||||
collator.compare(flags, "-h") == 0 ||
|
||||
collator.compare(flags, "-?") == 0) {
|
||||
} else if (collator.compare(flags, "--help") == 0 ||
|
||||
collator.compare(flags, "-h") == 0 ||
|
||||
collator.compare(flags, "-?") == 0 ||
|
||||
// -help: legacy.
|
||||
collator.compare(flags, "-help") == 0) {
|
||||
help = true;
|
||||
} else if (collator.compare(flags, "-conf") == 0) {
|
||||
i++;
|
||||
|
@ -4608,6 +4610,8 @@ public final class Main {
|
|||
System.err.printf(" %-20s%s\n", c, rb.getString(c.description));
|
||||
}
|
||||
System.err.println();
|
||||
System.err.println(rb.getString(
|
||||
"Use.keytool.help.for.all.available.commands"));
|
||||
System.err.println(rb.getString(
|
||||
"Use.keytool.command.name.help.for.usage.of.command.name"));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2018, 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
|
||||
|
@ -45,12 +45,12 @@ public class Resources extends java.util.ListResourceBundle {
|
|||
{"option.1.set.twice", "The %s option is specified multiple times. All except the last one will be ignored."},
|
||||
{"multiple.commands.1.2", "Only one command is allowed: both %1$s and %2$s were specified."},
|
||||
{"Use.keytool.help.for.all.available.commands",
|
||||
"Use \"keytool -help\" for all available commands"},
|
||||
"Use \"keytool -?, -h, or --help\" for this help message"},
|
||||
{"Key.and.Certificate.Management.Tool",
|
||||
"Key and Certificate Management Tool"},
|
||||
{"Commands.", "Commands:"},
|
||||
{"Use.keytool.command.name.help.for.usage.of.command.name",
|
||||
"Use \"keytool -command_name -help\" for usage of command_name.\n" +
|
||||
"Use \"keytool -command_name --help\" for usage of command_name.\n" +
|
||||
"Use the -conf <url> option to specify a pre-configured options file."},
|
||||
// keytool: help: commands
|
||||
{"Generates.a.certificate.request",
|
||||
|
@ -462,7 +462,7 @@ public class Resources extends java.util.ListResourceBundle {
|
|||
{"with.weak", "%s (weak)"},
|
||||
{"key.bit", "%1$d-bit %2$s key"},
|
||||
{"key.bit.weak", "%1$d-bit %2$s key (weak)"},
|
||||
{"unknown.size.1", "unknown size %s key"},
|
||||
{"unknown.size.1", "%s key of unknown size"},
|
||||
{".PATTERN.printX509Cert.with.weak",
|
||||
"Owner: {0}\nIssuer: {1}\nSerial number: {2}\nValid from: {3} until: {4}\nCertificate fingerprints:\n\t SHA1: {5}\n\t SHA256: {6}\nSignature algorithm name: {7}\nSubject Public Key Algorithm: {8}\nVersion: {9}"},
|
||||
{"PKCS.10.with.weak",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2018, 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
|
||||
|
@ -42,7 +42,7 @@ package sun.security.util;
|
|||
|
||||
public class LocalizedMessage {
|
||||
|
||||
private static final Resources resources = new Resources();
|
||||
private static final Resources RESOURCES = new Resources();
|
||||
|
||||
private final String key;
|
||||
|
||||
|
@ -59,16 +59,28 @@ public class LocalizedMessage {
|
|||
|
||||
/**
|
||||
* Return a localized string corresponding to the key stored in this
|
||||
* object, formatted with the provided arguments. When the VM is booted,
|
||||
* this method will obtain the correct localized message and format it
|
||||
* using java.text.MessageFormat. Otherwise, a non-localized string is
|
||||
* returned, and the formatting is performed by simplified formatting code.
|
||||
* object, formatted with the provided arguments. This method should only
|
||||
* be called when the VM is booted and all resources needed to obtain
|
||||
* and format the localized message are loaded (or can be loaded).
|
||||
*
|
||||
* @param arguments The arguments that should be placed in the message
|
||||
* @return A formatted message string
|
||||
*/
|
||||
public String format(Object... arguments) {
|
||||
return getMessage(key, arguments);
|
||||
public String formatLocalized(Object... arguments) {
|
||||
return getLocalized(key, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a non-localized string corresponding to the key stored in this
|
||||
* object, formatted with the provided arguments. All strings are obtained
|
||||
* from sun.security.util.Resources, and the formatting only supports
|
||||
* simple positional argument replacement (e.g. {1}).
|
||||
*
|
||||
* @param arguments The arguments that should be placed in the message
|
||||
* @return A formatted message string
|
||||
*/
|
||||
public String formatNonlocalized(Object... arguments) {
|
||||
return getNonlocalized(key, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,10 +93,10 @@ public class LocalizedMessage {
|
|||
* @param arguments The arguments that should be placed in the message
|
||||
* @return A formatted message string
|
||||
*/
|
||||
public static String getMessageUnbooted(String key,
|
||||
Object... arguments) {
|
||||
public static String getNonlocalized(String key,
|
||||
Object... arguments) {
|
||||
|
||||
String value = resources.getString(key);
|
||||
String value = RESOURCES.getString(key);
|
||||
if (arguments == null || arguments.length == 0) {
|
||||
return value;
|
||||
}
|
||||
|
@ -110,8 +122,7 @@ public class LocalizedMessage {
|
|||
try {
|
||||
int index = Integer.parseInt(indexStr);
|
||||
sb.append(arguments[index]);
|
||||
}
|
||||
catch(NumberFormatException e) {
|
||||
} catch (NumberFormatException e) {
|
||||
// argument index is not an integer
|
||||
throw new RuntimeException("not an integer: " + indexStr);
|
||||
}
|
||||
|
@ -123,29 +134,22 @@ public class LocalizedMessage {
|
|||
|
||||
/**
|
||||
* Return a localized string corresponding to the provided key, and
|
||||
* formatted with the provided arguments. When the VM is booted, this
|
||||
* method will obtain the correct localized message and format it using
|
||||
* java.text.MessageFormat. Otherwise, a non-localized string is returned,
|
||||
* and the formatting is performed by simplified formatting code.
|
||||
* formatted with the provided arguments. This method should only be
|
||||
* called when the VM is booted and all resources needed to obtain
|
||||
* and format the localized message are loaded (or can be loaded).
|
||||
*
|
||||
* @param key The key of the desired string in the security resource bundle
|
||||
* @param arguments The arguments that should be placed in the message
|
||||
* @return A formatted message string
|
||||
*/
|
||||
public static String getMessage(String key,
|
||||
Object... arguments) {
|
||||
public static String getLocalized(String key, Object... arguments) {
|
||||
|
||||
if (jdk.internal.misc.VM.isBooted()) {
|
||||
// Localization and formatting resources are available
|
||||
String value = ResourcesMgr.getString(key);
|
||||
if (arguments == null) {
|
||||
return value;
|
||||
}
|
||||
java.text.MessageFormat form = new java.text.MessageFormat(value);
|
||||
return form.format(arguments);
|
||||
} else {
|
||||
return getMessageUnbooted(key, arguments);
|
||||
String value = ResourcesMgr.getString(key);
|
||||
if (arguments == null) {
|
||||
return value;
|
||||
}
|
||||
java.text.MessageFormat form = new java.text.MessageFormat(value);
|
||||
return form.format(arguments);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 2018, 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
|
||||
|
@ -31,8 +31,8 @@
|
|||
*/
|
||||
|
||||
package sun.util.locale;
|
||||
import java.lang.ref.SoftReference;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
public final class BaseLocale {
|
||||
|
@ -48,26 +48,28 @@ public final class BaseLocale {
|
|||
|
||||
private volatile int hash;
|
||||
|
||||
// This method must be called only when creating the Locale.* constants.
|
||||
private BaseLocale(String language, String region) {
|
||||
this.language = language;
|
||||
this.script = "";
|
||||
this.region = region;
|
||||
this.variant = "";
|
||||
}
|
||||
|
||||
private BaseLocale(String language, String script, String region, String variant) {
|
||||
this.language = (language != null) ? LocaleUtils.toLowerString(language).intern() : "";
|
||||
this.script = (script != null) ? LocaleUtils.toTitleString(script).intern() : "";
|
||||
this.region = (region != null) ? LocaleUtils.toUpperString(region).intern() : "";
|
||||
this.variant = (variant != null) ? variant.intern() : "";
|
||||
// This method must be called with normalize = false only when creating the
|
||||
// Locale.* constants and non-normalized BaseLocale$Keys used for lookup.
|
||||
private BaseLocale(String language, String script, String region, String variant,
|
||||
boolean normalize) {
|
||||
if (normalize) {
|
||||
this.language = LocaleUtils.toLowerString(language).intern();
|
||||
this.script = LocaleUtils.toTitleString(script).intern();
|
||||
this.region = LocaleUtils.toUpperString(region).intern();
|
||||
this.variant = variant.intern();
|
||||
} else {
|
||||
this.language = language;
|
||||
this.script = script;
|
||||
this.region = region;
|
||||
this.variant = variant;
|
||||
}
|
||||
}
|
||||
|
||||
// Called for creating the Locale.* constants. No argument
|
||||
// validation is performed.
|
||||
public static BaseLocale createInstance(String language, String region) {
|
||||
BaseLocale base = new BaseLocale(language, region);
|
||||
CACHE.put(new Key(language, region), base);
|
||||
BaseLocale base = new BaseLocale(language, "", region, "", false);
|
||||
CACHE.put(new Key(base), base);
|
||||
return base;
|
||||
}
|
||||
|
||||
|
@ -84,7 +86,7 @@ public final class BaseLocale {
|
|||
}
|
||||
}
|
||||
|
||||
Key key = new Key(language, script, region, variant);
|
||||
Key key = new Key(language, script, region, variant, false);
|
||||
BaseLocale baseLocale = CACHE.get(key);
|
||||
return baseLocale;
|
||||
}
|
||||
|
@ -123,16 +125,16 @@ public final class BaseLocale {
|
|||
@Override
|
||||
public String toString() {
|
||||
StringJoiner sj = new StringJoiner(", ");
|
||||
if (language.length() > 0) {
|
||||
if (!language.isEmpty()) {
|
||||
sj.add("language=" + language);
|
||||
}
|
||||
if (script.length() > 0) {
|
||||
if (!script.isEmpty()) {
|
||||
sj.add("script=" + script);
|
||||
}
|
||||
if (region.length() > 0) {
|
||||
if (!region.isEmpty()) {
|
||||
sj.add("region=" + region);
|
||||
}
|
||||
if (variant.length() > 0) {
|
||||
if (!variant.isEmpty()) {
|
||||
sj.add("variant=" + variant);
|
||||
}
|
||||
return sj.toString();
|
||||
|
@ -155,10 +157,17 @@ public final class BaseLocale {
|
|||
}
|
||||
|
||||
private static final class Key {
|
||||
private final SoftReference<String> lang;
|
||||
private final SoftReference<String> scrt;
|
||||
private final SoftReference<String> regn;
|
||||
private final SoftReference<String> vart;
|
||||
/**
|
||||
* Keep a SoftReference to the Key data if normalized (actually used
|
||||
* as a cache key) and not initialized via the constant creation path.
|
||||
*
|
||||
* This allows us to avoid creating SoftReferences on lookup Keys
|
||||
* (which are short-lived) and for Locales created via
|
||||
* Locale#createConstant.
|
||||
*/
|
||||
private final SoftReference<BaseLocale> holderRef;
|
||||
private final BaseLocale holder;
|
||||
|
||||
private final boolean normalized;
|
||||
private final int hash;
|
||||
|
||||
|
@ -166,15 +175,16 @@ public final class BaseLocale {
|
|||
* Creates a Key. language and region must be normalized
|
||||
* (intern'ed in the proper case).
|
||||
*/
|
||||
private Key(String language, String region) {
|
||||
assert language.intern() == language
|
||||
&& region.intern() == region;
|
||||
|
||||
lang = new SoftReference<>(language);
|
||||
scrt = new SoftReference<>("");
|
||||
regn = new SoftReference<>(region);
|
||||
vart = new SoftReference<>("");
|
||||
private Key(BaseLocale locale) {
|
||||
this.holder = locale;
|
||||
this.holderRef = null;
|
||||
this.normalized = true;
|
||||
String language = locale.getLanguage();
|
||||
String region = locale.getRegion();
|
||||
assert LocaleUtils.toLowerString(language).intern() == language
|
||||
&& LocaleUtils.toUpperString(region).intern() == region
|
||||
&& locale.getVariant() == ""
|
||||
&& locale.getScript() == "";
|
||||
|
||||
int h = language.hashCode();
|
||||
if (region != "") {
|
||||
|
@ -186,51 +196,64 @@ public final class BaseLocale {
|
|||
hash = h;
|
||||
}
|
||||
|
||||
public Key(String language, String script, String region, String variant) {
|
||||
this(language, script, region, variant, false);
|
||||
private Key(String language, String script, String region,
|
||||
String variant, boolean normalize) {
|
||||
if (language == null) {
|
||||
language = "";
|
||||
}
|
||||
if (script == null) {
|
||||
script = "";
|
||||
}
|
||||
if (region == null) {
|
||||
region = "";
|
||||
}
|
||||
if (variant == null) {
|
||||
variant = "";
|
||||
}
|
||||
|
||||
BaseLocale locale = new BaseLocale(language, script, region, variant, normalize);
|
||||
this.normalized = normalize;
|
||||
if (normalized) {
|
||||
this.holderRef = new SoftReference<>(locale);
|
||||
this.holder = null;
|
||||
} else {
|
||||
this.holderRef = null;
|
||||
this.holder = locale;
|
||||
}
|
||||
this.hash = hashCode(locale);
|
||||
}
|
||||
|
||||
private Key(String language, String script, String region,
|
||||
String variant, boolean normalized) {
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
private int hashCode(BaseLocale locale) {
|
||||
int h = 0;
|
||||
if (language != null) {
|
||||
lang = new SoftReference<>(language);
|
||||
int len = language.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
h = 31*h + LocaleUtils.toLower(language.charAt(i));
|
||||
}
|
||||
} else {
|
||||
lang = new SoftReference<>("");
|
||||
String lang = locale.getLanguage();
|
||||
int len = lang.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
h = 31*h + LocaleUtils.toLower(lang.charAt(i));
|
||||
}
|
||||
if (script != null) {
|
||||
scrt = new SoftReference<>(script);
|
||||
int len = script.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
h = 31*h + LocaleUtils.toLower(script.charAt(i));
|
||||
}
|
||||
} else {
|
||||
scrt = new SoftReference<>("");
|
||||
String scrt = locale.getScript();
|
||||
len = scrt.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
h = 31*h + LocaleUtils.toLower(scrt.charAt(i));
|
||||
}
|
||||
if (region != null) {
|
||||
regn = new SoftReference<>(region);
|
||||
int len = region.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
h = 31*h + LocaleUtils.toLower(region.charAt(i));
|
||||
}
|
||||
} else {
|
||||
regn = new SoftReference<>("");
|
||||
String regn = locale.getRegion();
|
||||
len = regn.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
h = 31*h + LocaleUtils.toLower(regn.charAt(i));
|
||||
}
|
||||
if (variant != null) {
|
||||
vart = new SoftReference<>(variant);
|
||||
int len = variant.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
h = 31*h + variant.charAt(i);
|
||||
}
|
||||
} else {
|
||||
vart = new SoftReference<>("");
|
||||
String vart = locale.getVariant();
|
||||
len = vart.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
h = 31*h + vart.charAt(i);
|
||||
}
|
||||
hash = h;
|
||||
this.normalized = normalized;
|
||||
return h;
|
||||
}
|
||||
|
||||
private BaseLocale getBaseLocale() {
|
||||
return (holder == null) ? holderRef.get() : holder;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -238,46 +261,31 @@ public final class BaseLocale {
|
|||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj instanceof Key && this.hash == ((Key)obj).hash) {
|
||||
String tl = this.lang.get();
|
||||
String ol = ((Key)obj).lang.get();
|
||||
if (tl != null && ol != null &&
|
||||
LocaleUtils.caseIgnoreMatch(ol, tl)) {
|
||||
String ts = this.scrt.get();
|
||||
String os = ((Key)obj).scrt.get();
|
||||
if (ts != null && os != null &&
|
||||
LocaleUtils.caseIgnoreMatch(os, ts)) {
|
||||
String tr = this.regn.get();
|
||||
String or = ((Key)obj).regn.get();
|
||||
if (tr != null && or != null &&
|
||||
LocaleUtils.caseIgnoreMatch(or, tr)) {
|
||||
String tv = this.vart.get();
|
||||
String ov = ((Key)obj).vart.get();
|
||||
return (ov != null && ov.equals(tv));
|
||||
}
|
||||
}
|
||||
BaseLocale other = ((Key) obj).getBaseLocale();
|
||||
BaseLocale locale = this.getBaseLocale();
|
||||
if (other != null && locale != null
|
||||
&& LocaleUtils.caseIgnoreMatch(other.getLanguage(), locale.getLanguage())
|
||||
&& LocaleUtils.caseIgnoreMatch(other.getScript(), locale.getScript())
|
||||
&& LocaleUtils.caseIgnoreMatch(other.getRegion(), locale.getRegion())
|
||||
// variant is case sensitive in JDK!
|
||||
&& other.getVariant().equals(locale.getVariant())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public static Key normalize(Key key) {
|
||||
if (key.normalized) {
|
||||
return key;
|
||||
}
|
||||
|
||||
String lang = LocaleUtils.toLowerString(key.lang.get()).intern();
|
||||
String scrt = LocaleUtils.toTitleString(key.scrt.get()).intern();
|
||||
String regn = LocaleUtils.toUpperString(key.regn.get()).intern();
|
||||
String vart = key.vart.get().intern(); // preserve upper/lower cases
|
||||
|
||||
return new Key(lang, scrt, regn, vart, true);
|
||||
// Only normalized keys may be softly referencing the data holder
|
||||
assert (key.holder != null && key.holderRef == null);
|
||||
BaseLocale locale = key.holder;
|
||||
return new Key(locale.getLanguage(), locale.getScript(),
|
||||
locale.getRegion(), locale.getVariant(), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,18 +296,12 @@ public final class BaseLocale {
|
|||
|
||||
@Override
|
||||
protected Key normalizeKey(Key key) {
|
||||
assert key.lang.get() != null &&
|
||||
key.scrt.get() != null &&
|
||||
key.regn.get() != null &&
|
||||
key.vart.get() != null;
|
||||
|
||||
return Key.normalize(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BaseLocale createObject(Key key) {
|
||||
return new BaseLocale(key.lang.get(), key.scrt.get(),
|
||||
key.regn.get(), key.vart.get());
|
||||
return Key.normalize(key).getBaseLocale();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -37,8 +37,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public abstract class LocaleObjectCache<K, V> {
|
||||
private ConcurrentMap<K, CacheEntry<K, V>> map;
|
||||
private ReferenceQueue<V> queue = new ReferenceQueue<>();
|
||||
private final ConcurrentMap<K, CacheEntry<K, V>> map;
|
||||
private final ReferenceQueue<V> queue = new ReferenceQueue<>();
|
||||
|
||||
public LocaleObjectCache() {
|
||||
this(16, 0.75f, 16);
|
||||
|
@ -57,17 +57,14 @@ public abstract class LocaleObjectCache<K, V> {
|
|||
value = entry.get();
|
||||
}
|
||||
if (value == null) {
|
||||
V newVal = createObject(key);
|
||||
// make sure key is normalized *after* the object creation
|
||||
// so that newVal is assured to be created from a valid key.
|
||||
key = normalizeKey(key);
|
||||
V newVal = createObject(key);
|
||||
if (key == null || newVal == null) {
|
||||
// subclass must return non-null key/value object
|
||||
return null;
|
||||
}
|
||||
|
||||
CacheEntry<K, V> newEntry = new CacheEntry<>(key, newVal, queue);
|
||||
|
||||
entry = map.putIfAbsent(key, newEntry);
|
||||
if (entry == null) {
|
||||
value = newVal;
|
||||
|
@ -92,7 +89,7 @@ public abstract class LocaleObjectCache<K, V> {
|
|||
private void cleanStaleEntries() {
|
||||
CacheEntry<K, V> entry;
|
||||
while ((entry = (CacheEntry<K, V>)queue.poll()) != null) {
|
||||
map.remove(entry.getKey());
|
||||
map.remove(entry.getKey(), entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue