This commit is contained in:
Mikael Vidstedt 2018-08-09 10:08:07 -07:00
commit 83a51d869e
49 changed files with 4929 additions and 139 deletions

View File

@ -499,6 +499,7 @@ e1b3def126240d5433902f3cb0e91a4c27f6db50 jdk-11+18
1edcf36fe15f79d6228d1a63eb680878e2386480 jdk-11+23
ea900a7dc7d77dee30865c60eabd87fc24b1037c jdk-11+24
331888ea4a788df801b1edf8836646cd25fc758b jdk-11+25
945ba9278a272a5477ffb1b3ea1b04174fed8036 jdk-11+26
69b438908512d3dfef5852c6a843a5778333a309 jdk-12+2
990db216e7199b2ba9989d8fa20b657e0ca7d969 jdk-12+3
499b873761d8e8a1cc4aa649daf04cbe98cbce77 jdk-12+4

View File

@ -1094,7 +1094,7 @@ int NetworkPerformanceInterface::NetworkPerformance::network_utilization(Network
NetworkInterface* ret = NULL;
for (cur_address = addresses; cur_address != NULL; cur_address = cur_address->ifa_next) {
if (cur_address->ifa_addr->sa_family != AF_PACKET) {
if ((cur_address->ifa_addr == NULL) || (cur_address->ifa_addr->sa_family != AF_PACKET)) {
continue;
}
@ -1105,6 +1105,7 @@ int NetworkPerformanceInterface::NetworkPerformance::network_utilization(Network
ret = cur;
}
freeifaddrs(addresses);
*network_interfaces = ret;
return OS_OK;

View File

@ -808,6 +808,7 @@ int NetworkPerformanceInterface::NetworkPerformance::network_utilization(Network
}
}
kstat_close(ctl);
*network_interfaces = ret;
return OS_OK;

View File

@ -497,6 +497,7 @@ class ComputeLinearScanOrder : public StackObj {
// computation of final block order
BlockBegin* common_dominator(BlockBegin* a, BlockBegin* b);
void compute_dominator(BlockBegin* cur, BlockBegin* parent);
void compute_dominator_impl(BlockBegin* cur, BlockBegin* parent);
int compute_weight(BlockBegin* cur);
bool ready_for_processing(BlockBegin* cur);
void sort_into_work_list(BlockBegin* b);
@ -770,6 +771,14 @@ BlockBegin* ComputeLinearScanOrder::common_dominator(BlockBegin* a, BlockBegin*
}
void ComputeLinearScanOrder::compute_dominator(BlockBegin* cur, BlockBegin* parent) {
init_visited();
compute_dominator_impl(cur, parent);
}
void ComputeLinearScanOrder::compute_dominator_impl(BlockBegin* cur, BlockBegin* parent) {
// Mark as visited to avoid recursive calls with same parent
set_visited(cur);
if (cur->dominator() == NULL) {
TRACE_LINEAR_SCAN(4, tty->print_cr("DOM: initializing dominator of B%d to B%d", cur->block_id(), parent->block_id()));
cur->set_dominator(parent);
@ -788,7 +797,9 @@ void ComputeLinearScanOrder::compute_dominator(BlockBegin* cur, BlockBegin* pare
int num_cur_xhandler = cur->number_of_exception_handlers();
for (int j = 0; j < num_cur_xhandler; j++) {
BlockBegin* xhandler = cur->exception_handler_at(j);
compute_dominator(xhandler, parent);
if (!is_visited(xhandler)) {
compute_dominator_impl(xhandler, parent);
}
}
}

View File

@ -1070,6 +1070,11 @@ jceks.key.serialFilter = java.base/java.lang.Enum;java.base/java.security.KeyRep
# case-insensitive. Leading and trailing whitespaces, surrounding each value,
# are ignored. Unknown values are ignored.
#
# NOTE: Use caution before setting this property. Setting this property
# exposes sensitive information in Exceptions, which could, for example,
# propagate to untrusted code or be emitted in stack traces that are
# inadvertently disclosed and made accessible over a public network.
#
# The categories are:
#
# hostInfo - IOExceptions thrown by java.net.Socket and the socket types in the

View File

@ -42,7 +42,6 @@ import java.io.FilePermission;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Objects;
@ -85,10 +84,6 @@ import sun.security.util.SecurityConstants;
* application is executed, it will be executed on the same system as
* the one on which the Java application was launched.
*
* <p> Note: the methods in the {@code Desktop} class may require
* platform-dependent permissions in addition to those described in the
* specification.
*
* @see Action
*
* @since 1.6
@ -389,11 +384,12 @@ public class Desktop {
/**
* Calls to the security manager's {@code checkPermission} method with
* an {@code AWTPermission("showWindowWithoutWarningBanner")}
* permission.
* Calls to the security manager's {@code checkPermission} method with an
* {@code AWTPermission("showWindowWithoutWarningBanner")} permission. This
* permission is needed, because we cannot add a security warning icon to
* the windows of the external native application.
*/
private void checkAWTPermission(){
private void checkAWTPermission() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new AWTPermission(
@ -938,7 +934,11 @@ public class Desktop {
* and registered in the Info.plist with CFBundleHelpBookFolder
*
* @throws SecurityException if a security manager exists and it denies the
* {@code RuntimePermission("canProcessApplicationEvents")} permission.
* {@code RuntimePermission("canProcessApplicationEvents")}
* permission, or it denies the
* {@code AWTPermission("showWindowWithoutWarningBanner")}
* permission, or the calling thread is not allowed to create a
* subprocess
* @throws UnsupportedOperationException if the current platform
* does not support the {@link Desktop.Action#APP_HELP_VIEWER} action
* @since 9
@ -982,12 +982,15 @@ public class Desktop {
* @param file the file
* @throws SecurityException If a security manager exists and its
* {@link SecurityManager#checkRead(java.lang.String)} method
* denies read access to the file
* denies read access to the file or to its parent, or it denies the
* {@code AWTPermission("showWindowWithoutWarningBanner")}
* permission, or the calling thread is not allowed to create a
* subprocess
* @throws UnsupportedOperationException if the current platform
* does not support the {@link Desktop.Action#BROWSE_FILE_DIR} action
* @throws NullPointerException if {@code file} is {@code null}
* @throws IllegalArgumentException if the specified file doesn't
* exist
* @throws IllegalArgumentException if the specified file or its parent
* doesn't exist
* @since 9
*/
public void browseFileDirectory(File file) {
@ -1014,8 +1017,7 @@ public class Desktop {
* @throws UnsupportedOperationException if the current platform
* does not support the {@link Desktop.Action#MOVE_TO_TRASH} action
* @throws NullPointerException if {@code file} is {@code null}
* @throws IllegalArgumentException if the specified file doesn't
* exist
* @throws IllegalArgumentException if the specified file doesn't exist
*
* @since 9
*/

View File

@ -34,6 +34,7 @@ import java.net.ProxySelector;
import java.net.URLPermission;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
@ -84,6 +85,7 @@ import jdk.internal.net.http.HttpClientBuilderImpl;
* <pre>{@code HttpClient client = HttpClient.newBuilder()
* .version(Version.HTTP_1_1)
* .followRedirects(Redirect.NORMAL)
* .connectTimeout(Duration.ofSeconds(20))
* .proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 80)))
* .authenticator(Authenticator.getDefault())
* .build();
@ -94,7 +96,7 @@ import jdk.internal.net.http.HttpClientBuilderImpl;
* <p><b>Asynchronous Example</b>
* <pre>{@code HttpRequest request = HttpRequest.newBuilder()
* .uri(URI.create("https://foo.com/"))
* .timeout(Duration.ofMinutes(1))
* .timeout(Duration.ofMinutes(2))
* .header("Content-Type", "application/json")
* .POST(BodyPublishers.ofFile(Paths.get("file.json")))
* .build();
@ -196,6 +198,26 @@ public abstract class HttpClient {
*/
public Builder cookieHandler(CookieHandler cookieHandler);
/**
* Sets the connect timeout duration for this client.
*
* <p> In the case where a new connection needs to be established, if
* the connection cannot be established within the given {@code
* duration}, then {@link HttpClient#send(HttpRequest,BodyHandler)
* HttpClient::send} throws an {@link HttpConnectTimeoutException}, or
* {@link HttpClient#sendAsync(HttpRequest,BodyHandler)
* HttpClient::sendAsync} completes exceptionally with an
* {@code HttpConnectTimeoutException}. If a new connection does not
* need to be established, for example if a connection can be reused
* from a previous request, then this timeout duration has no effect.
*
* @param duration the duration to allow the underlying connection to be
* established
* @return this builder
* @throws IllegalArgumentException if the duration is non-positive
*/
public Builder connectTimeout(Duration duration);
/**
* Sets an {@code SSLContext}.
*
@ -344,6 +366,17 @@ public abstract class HttpClient {
*/
public abstract Optional<CookieHandler> cookieHandler();
/**
* Returns an {@code Optional} containing the <i>connect timeout duration</i>
* for this client. If the {@linkplain Builder#connectTimeout(Duration)
* connect timeout duration} was not set in the client's builder, then the
* {@code Optional} is empty.
*
* @return an {@code Optional} containing this client's connect timeout
* duration
*/
public abstract Optional<Duration> connectTimeout();
/**
* Returns the follow redirects policy for this client. The default value
* for client's built by builders that do not specify a redirect policy is

View File

@ -0,0 +1,48 @@
/*
* 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.http;
/**
* Thrown when a connection, over which an {@code HttpRequest} is intended to be
* sent, is not successfully established within a specified time period.
*
* @since 11
*/
public class HttpConnectTimeoutException extends HttpTimeoutException {
private static final long serialVersionUID = 321L + 11L;
/**
* Constructs an {@code HttpConnectTimeoutException} with the given detail
* message.
*
* @param message
* The detail message; can be {@code null}
*/
public HttpConnectTimeoutException(String message) {
super(message);
}
}

View File

@ -80,11 +80,9 @@ abstract class AbstractAsyncSSLConnection extends HttpConnection
engine = createEngine(context, serverName.getName(), port, sslParameters);
}
abstract HttpConnection plainConnection();
abstract SSLTube getConnectionFlow();
final CompletableFuture<String> getALPN() {
assert connected();
return getConnectionFlow().getALPN();
}

View File

@ -28,6 +28,8 @@ package jdk.internal.net.http;
import java.net.InetSocketAddress;
import java.nio.channels.SocketChannel;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import jdk.internal.net.http.common.MinimalFuture;
import jdk.internal.net.http.common.SSLTube;
import jdk.internal.net.http.common.Utils;
@ -49,14 +51,9 @@ class AsyncSSLConnection extends AbstractAsyncSSLConnection {
}
@Override
PlainHttpConnection plainConnection() {
return plainConnection;
}
@Override
public CompletableFuture<Void> connectAsync() {
public CompletableFuture<Void> connectAsync(Exchange<?> exchange) {
return plainConnection
.connectAsync()
.connectAsync(exchange)
.thenApply( unused -> {
// create the SSLTube wrapping the SocketTube, with the given engine
flow = new SSLTube(engine,
@ -66,6 +63,21 @@ class AsyncSSLConnection extends AbstractAsyncSSLConnection {
return null; } );
}
@Override
public CompletableFuture<Void> finishConnect() {
// The actual ALPN value, which may be the empty string, is not
// interesting at this point, only that the handshake has completed.
return getALPN()
.handle((String unused, Throwable ex) -> {
if (ex == null) {
return plainConnection.finishConnect();
} else {
plainConnection.close();
return MinimalFuture.<Void>failedFuture(ex);
} })
.thenCompose(Function.identity());
}
@Override
boolean connected() {
return plainConnection.connected();

View File

@ -29,6 +29,8 @@ import java.net.InetSocketAddress;
import java.nio.channels.SocketChannel;
import java.util.concurrent.CompletableFuture;
import java.net.http.HttpHeaders;
import java.util.function.Function;
import jdk.internal.net.http.common.MinimalFuture;
import jdk.internal.net.http.common.SSLTube;
import jdk.internal.net.http.common.Utils;
@ -53,13 +55,13 @@ class AsyncSSLTunnelConnection extends AbstractAsyncSSLConnection {
}
@Override
public CompletableFuture<Void> connectAsync() {
public CompletableFuture<Void> connectAsync(Exchange<?> exchange) {
if (debug.on()) debug.log("Connecting plain tunnel connection");
// This will connect the PlainHttpConnection flow, so that
// its HttpSubscriber and HttpPublisher are subscribed to the
// SocketTube
return plainConnection
.connectAsync()
.connectAsync(exchange)
.thenApply( unused -> {
if (debug.on()) debug.log("creating SSLTube");
// create the SSLTube wrapping the SocketTube, with the given engine
@ -70,6 +72,21 @@ class AsyncSSLTunnelConnection extends AbstractAsyncSSLConnection {
return null;} );
}
@Override
public CompletableFuture<Void> finishConnect() {
// The actual ALPN value, which may be the empty string, is not
// interesting at this point, only that the handshake has completed.
return getALPN()
.handle((String unused, Throwable ex) -> {
if (ex == null) {
return plainConnection.finishConnect();
} else {
plainConnection.close();
return MinimalFuture.<Void>failedFuture(ex);
} })
.thenCompose(Function.identity());
}
@Override
boolean isTunnel() { return true; }
@ -86,11 +103,6 @@ class AsyncSSLTunnelConnection extends AbstractAsyncSSLConnection {
return "AsyncSSLTunnelConnection: " + super.toString();
}
@Override
PlainTunnelingConnection plainConnection() {
return plainConnection;
}
@Override
ConnectionPool.CacheKey cacheKey() {
return ConnectionPool.cacheKey(address, plainConnection.proxyAddr);

View File

@ -83,6 +83,10 @@ final class Exchange<T> {
final PushGroup<T> pushGroup;
final String dbgTag;
// Keeps track of the underlying connection when establishing an HTTP/2
// exchange so that it can be aborted/timed out mid setup.
final ConnectionAborter connectionAborter = new ConnectionAborter();
Exchange(HttpRequestImpl request, MultiExchange<T> multi) {
this.request = request;
this.upgrading = false;
@ -125,6 +129,27 @@ final class Exchange<T> {
return client;
}
// Keeps track of the underlying connection when establishing an HTTP/2
// exchange so that it can be aborted/timed out mid setup.
static final class ConnectionAborter {
private volatile HttpConnection connection;
void connection(HttpConnection connection) {
this.connection = connection;
}
void closeConnection() {
HttpConnection connection = this.connection;
this.connection = null;
if (connection != null) {
try {
connection.close();
} catch (Throwable t) {
// ignore
}
}
}
}
public CompletableFuture<T> readBodyAsync(HttpResponse.BodyHandler<T> handler) {
// If we received a 407 while establishing the exchange
@ -179,6 +204,7 @@ final class Exchange<T> {
}
public void cancel(IOException cause) {
if (debug.on()) debug.log("cancel exchImpl: %s, with \"%s\"", exchImpl, cause);
// If the impl is non null, propagate the exception right away.
// Otherwise record it so that it can be propagated once the
// exchange impl has been established.
@ -190,6 +216,11 @@ final class Exchange<T> {
} else {
// no impl yet. record the exception
failed = cause;
// abort/close the connection if setting up the exchange. This can
// be important when setting up HTTP/2
connectionAborter.closeConnection();
// now call checkCancelled to recheck the impl.
// if the failed state is set and the impl is not null, reset
// the failed state and propagate the exception to the impl.

View File

@ -85,7 +85,7 @@ abstract class ExchangeImpl<T> {
} else {
Http2ClientImpl c2 = exchange.client().client2(); // #### improve
HttpRequestImpl request = exchange.request();
CompletableFuture<Http2Connection> c2f = c2.getConnectionFor(request);
CompletableFuture<Http2Connection> c2f = c2.getConnectionFor(request, exchange);
if (debug.on())
debug.log("get: Trying to get HTTP/2 connection");
return c2f.handle((h2c, t) -> createExchangeImpl(h2c, t, exchange, connection))

View File

@ -233,7 +233,8 @@ class Http1Exchange<T> extends ExchangeImpl<T> {
CompletableFuture<Void> connectCF;
if (!connection.connected()) {
if (debug.on()) debug.log("initiating connect async");
connectCF = connection.connectAsync();
connectCF = connection.connectAsync(exchange)
.thenCompose(unused -> connection.finishConnect());
Throwable cancelled;
synchronized (lock) {
if ((cancelled = failed) == null) {

View File

@ -90,7 +90,8 @@ class Http2ClientImpl {
* 3. completes normally with null: no connection in cache for h2c or h2 failed previously
* 4. completes normally with connection: h2 or h2c connection in cache. Use it.
*/
CompletableFuture<Http2Connection> getConnectionFor(HttpRequestImpl req) {
CompletableFuture<Http2Connection> getConnectionFor(HttpRequestImpl req,
Exchange<?> exchange) {
URI uri = req.uri();
InetSocketAddress proxy = req.proxy();
String key = Http2Connection.keyFor(uri, proxy);
@ -123,7 +124,7 @@ class Http2ClientImpl {
}
}
return Http2Connection
.createAsync(req, this)
.createAsync(req, this, exchange)
.whenComplete((conn, t) -> {
synchronized (Http2ClientImpl.this) {
if (conn != null) {

View File

@ -353,7 +353,8 @@ class Http2Connection {
// Requires TLS handshake. So, is really async
static CompletableFuture<Http2Connection> createAsync(HttpRequestImpl request,
Http2ClientImpl h2client) {
Http2ClientImpl h2client,
Exchange<?> exchange) {
assert request.secure();
AbstractAsyncSSLConnection connection = (AbstractAsyncSSLConnection)
HttpConnection.getConnection(request.getAddress(),
@ -361,7 +362,12 @@ class Http2Connection {
request,
HttpClient.Version.HTTP_2);
return connection.connectAsync()
// Expose the underlying connection to the exchange's aborter so it can
// be closed if a timeout occurs.
exchange.connectionAborter.connection(connection);
return connection.connectAsync(exchange)
.thenCompose(unused -> connection.finishConnect())
.thenCompose(unused -> checkSSLConfig(connection))
.thenCompose(notused-> {
CompletableFuture<Http2Connection> cf = new MinimalFuture<>();

View File

@ -28,6 +28,7 @@ package jdk.internal.net.http;
import java.net.Authenticator;
import java.net.CookieHandler;
import java.net.ProxySelector;
import java.time.Duration;
import java.util.concurrent.Executor;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
@ -38,6 +39,7 @@ import static java.util.Objects.requireNonNull;
public class HttpClientBuilderImpl implements HttpClient.Builder {
CookieHandler cookieHandler;
Duration connectTimeout;
HttpClient.Redirect followRedirects;
ProxySelector proxy;
Authenticator authenticator;
@ -55,6 +57,14 @@ public class HttpClientBuilderImpl implements HttpClient.Builder {
return this;
}
@Override
public HttpClientBuilderImpl connectTimeout(Duration duration) {
requireNonNull(duration);
if (duration.isNegative() || Duration.ZERO.equals(duration))
throw new IllegalArgumentException("Invalid duration: " + duration);
this.connectTimeout = duration;
return this;
}
@Override
public HttpClientBuilderImpl sslContext(SSLContext sslContext) {

View File

@ -30,6 +30,7 @@ import java.lang.ref.Reference;
import java.net.Authenticator;
import java.net.CookieHandler;
import java.net.ProxySelector;
import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
@ -69,6 +70,11 @@ final class HttpClientFacade extends HttpClient implements Trackable {
return impl.cookieHandler();
}
@Override
public Optional<Duration> connectTimeout() {
return impl.connectTimeout();
}
@Override
public Redirect followRedirects() {
return impl.followRedirects();

View File

@ -35,6 +35,7 @@ import java.net.Authenticator;
import java.net.ConnectException;
import java.net.CookieHandler;
import java.net.ProxySelector;
import java.net.http.HttpConnectTimeoutException;
import java.net.http.HttpTimeoutException;
import java.nio.ByteBuffer;
import java.nio.channels.CancelledKeyException;
@ -47,6 +48,7 @@ import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.NoSuchAlgorithmException;
import java.security.PrivilegedAction;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
@ -154,6 +156,7 @@ final class HttpClientImpl extends HttpClient implements Trackable {
}
private final CookieHandler cookieHandler;
private final Duration connectTimeout;
private final Redirect followRedirects;
private final Optional<ProxySelector> userProxySelector;
private final ProxySelector proxySelector;
@ -278,6 +281,7 @@ final class HttpClientImpl extends HttpClient implements Trackable {
facadeRef = new WeakReference<>(facadeFactory.createFacade(this));
client2 = new Http2ClientImpl(this);
cookieHandler = builder.cookieHandler;
connectTimeout = builder.connectTimeout;
followRedirects = builder.followRedirects == null ?
Redirect.NEVER : builder.followRedirects;
this.userProxySelector = Optional.ofNullable(builder.proxy);
@ -547,6 +551,10 @@ final class HttpClientImpl extends HttpClient implements Trackable {
throw new IllegalArgumentException(msg, throwable);
} else if (throwable instanceof SecurityException) {
throw new SecurityException(msg, throwable);
} else if (throwable instanceof HttpConnectTimeoutException) {
HttpConnectTimeoutException hcte = new HttpConnectTimeoutException(msg);
hcte.initCause(throwable);
throw hcte;
} else if (throwable instanceof HttpTimeoutException) {
throw new HttpTimeoutException(msg);
} else if (throwable instanceof ConnectException) {
@ -1123,6 +1131,11 @@ final class HttpClientImpl extends HttpClient implements Trackable {
return Optional.ofNullable(cookieHandler);
}
@Override
public Optional<Duration> connectTimeout() {
return Optional.ofNullable(connectTimeout);
}
@Override
public Optional<ProxySelector> proxy() {
return this.userProxySelector;

View File

@ -108,9 +108,20 @@ abstract class HttpConnection implements Closeable {
return client;
}
//public abstract void connect() throws IOException, InterruptedException;
/**
* Initiates the connect phase.
*
* Returns a CompletableFuture that completes when the underlying
* TCP connection has been established or an error occurs.
*/
public abstract CompletableFuture<Void> connectAsync(Exchange<?> exchange);
public abstract CompletableFuture<Void> connectAsync();
/**
* Finishes the connection phase.
*
* Returns a CompletableFuture that completes when any additional,
* type specific, setup has been done. Must be called after connectAsync. */
public abstract CompletableFuture<Void> finishConnect();
/** Tells whether, or not, this connection is connected to its destination. */
abstract boolean connected();

View File

@ -27,7 +27,7 @@ package jdk.internal.net.http;
import java.io.IOException;
import java.net.ConnectException;
import java.time.Duration;
import java.net.http.HttpConnectTimeoutException;
import java.util.Iterator;
import java.util.LinkedList;
import java.security.AccessControlContext;
@ -88,7 +88,7 @@ class MultiExchange<T> {
);
private final LinkedList<HeaderFilter> filters;
TimedEvent timedEvent;
ResponseTimerEvent responseTimerEvent;
volatile boolean cancelled;
final PushGroup<T> pushGroup;
@ -134,7 +134,7 @@ class MultiExchange<T> {
this.exchange = new Exchange<>(request, this);
}
private synchronized Exchange<T> getExchange() {
synchronized Exchange<T> getExchange() {
return exchange;
}
@ -157,8 +157,8 @@ class MultiExchange<T> {
}
private void cancelTimer() {
if (timedEvent != null) {
client.cancelTimer(timedEvent);
if (responseTimerEvent != null) {
client.cancelTimer(responseTimerEvent);
}
}
@ -220,8 +220,8 @@ class MultiExchange<T> {
cf = failedFuture(new IOException("Too many retries", retryCause));
} else {
if (currentreq.timeout().isPresent()) {
timedEvent = new TimedEvent(currentreq.timeout().get());
client.registerTimer(timedEvent);
responseTimerEvent = ResponseTimerEvent.of(this);
client.registerTimer(responseTimerEvent);
}
try {
// 1. apply request filters
@ -344,7 +344,9 @@ class MultiExchange<T> {
}
}
if (cancelled && t instanceof IOException) {
t = new HttpTimeoutException("request timed out");
if (!(t instanceof HttpTimeoutException)) {
t = toTimeoutException((IOException)t);
}
} else if (retryOnFailure(t)) {
Throwable cause = retryCause(t);
@ -378,17 +380,24 @@ class MultiExchange<T> {
return failedFuture(t);
}
class TimedEvent extends TimeoutEvent {
TimedEvent(Duration duration) {
super(duration);
}
@Override
public void handle() {
if (debug.on()) {
debug.log("Cancelling MultiExchange due to timeout for request %s",
request);
private HttpTimeoutException toTimeoutException(IOException ioe) {
HttpTimeoutException t = null;
// more specific, "request timed out", when connected
Exchange<?> exchange = getExchange();
if (exchange != null) {
ExchangeImpl<?> exchangeImpl = exchange.exchImpl;
if (exchangeImpl != null) {
if (exchangeImpl.connection().connected()) {
t = new HttpTimeoutException("request timed out");
t.initCause(ioe);
}
}
cancel(new HttpTimeoutException("request timed out"));
}
if (t == null) {
t = new HttpConnectTimeoutException("HTTP connect timed out");
t.initCause(new ConnectException("HTTP connect timed out"));
}
return t;
}
}

View File

@ -26,6 +26,7 @@
package jdk.internal.net.http;
import java.io.IOException;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.channels.SelectableChannel;
@ -34,6 +35,7 @@ import java.nio.channels.SocketChannel;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import jdk.internal.net.http.common.FlowTube;
import jdk.internal.net.http.common.Log;
@ -53,9 +55,52 @@ class PlainHttpConnection extends HttpConnection {
private final PlainHttpPublisher writePublisher = new PlainHttpPublisher(reading);
private volatile boolean connected;
private boolean closed;
private volatile ConnectTimerEvent connectTimerEvent; // may be null
// should be volatile to provide proper synchronization(visibility) action
/**
* Returns a ConnectTimerEvent iff there is a connect timeout duration,
* otherwise null.
*/
private ConnectTimerEvent newConnectTimer(Exchange<?> exchange,
CompletableFuture<Void> cf) {
Duration duration = client().connectTimeout().orElse(null);
if (duration != null) {
ConnectTimerEvent cte = new ConnectTimerEvent(duration, exchange, cf);
return cte;
}
return null;
}
final class ConnectTimerEvent extends TimeoutEvent {
private final CompletableFuture<Void> cf;
private final Exchange<?> exchange;
ConnectTimerEvent(Duration duration,
Exchange<?> exchange,
CompletableFuture<Void> cf) {
super(duration);
this.exchange = exchange;
this.cf = cf;
}
@Override
public void handle() {
if (debug.on()) {
debug.log("HTTP connect timed out");
}
ConnectException ce = new ConnectException("HTTP connect timed out");
exchange.multi.cancel(ce);
client().theExecutor().execute(() -> cf.completeExceptionally(ce));
}
@Override
public String toString() {
return "ConnectTimerEvent, " + super.toString();
}
}
final class ConnectEvent extends AsyncEvent {
private final CompletableFuture<Void> cf;
@ -85,7 +130,6 @@ class PlainHttpConnection extends HttpConnection {
if (debug.on())
debug.log("ConnectEvent: connect finished: %s Local addr: %s",
finished, chan.getLocalAddress());
connected = true;
// complete async since the event runs on the SelectorManager thread
cf.completeAsync(() -> null, client().theExecutor());
} catch (Throwable e) {
@ -103,12 +147,20 @@ class PlainHttpConnection extends HttpConnection {
}
@Override
public CompletableFuture<Void> connectAsync() {
public CompletableFuture<Void> connectAsync(Exchange<?> exchange) {
CompletableFuture<Void> cf = new MinimalFuture<>();
try {
assert !connected : "Already connected";
assert !chan.isBlocking() : "Unexpected blocking channel";
boolean finished = false;
boolean finished;
connectTimerEvent = newConnectTimer(exchange, cf);
if (connectTimerEvent != null) {
if (debug.on())
debug.log("registering connect timer: " + connectTimerEvent);
client().registerTimer(connectTimerEvent);
}
PrivilegedExceptionAction<Boolean> pa =
() -> chan.connect(Utils.resolveAddress(address));
try {
@ -118,7 +170,6 @@ class PlainHttpConnection extends HttpConnection {
}
if (finished) {
if (debug.on()) debug.log("connect finished without blocking");
connected = true;
cf.complete(null);
} else {
if (debug.on()) debug.log("registering connect event");
@ -136,6 +187,16 @@ class PlainHttpConnection extends HttpConnection {
return cf;
}
@Override
public CompletableFuture<Void> finishConnect() {
assert connected == false;
if (debug.on()) debug.log("finishConnect, setting connected=true");
connected = true;
if (connectTimerEvent != null)
client().cancelTimer(connectTimerEvent);
return MinimalFuture.completedFuture(null);
}
@Override
SocketChannel channel() {
return chan;
@ -210,6 +271,8 @@ class PlainHttpConnection extends HttpConnection {
Log.logTrace("Closing: " + toString());
if (debug.on())
debug.log("Closing channel: " + client().debugInterestOps(chan));
if (connectTimerEvent != null)
client().cancelTimer(connectTimerEvent);
chan.close();
tube.signalClosed();
} catch (IOException e) {

View File

@ -26,11 +26,13 @@
package jdk.internal.net.http;
import java.io.IOException;
import java.lang.System.Logger.Level;
import java.net.InetSocketAddress;
import java.net.http.HttpTimeoutException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.function.Function;
import java.net.http.HttpHeaders;
import jdk.internal.net.http.common.FlowTube;
@ -60,9 +62,10 @@ final class PlainTunnelingConnection extends HttpConnection {
}
@Override
public CompletableFuture<Void> connectAsync() {
public CompletableFuture<Void> connectAsync(Exchange<?> exchange) {
if (debug.on()) debug.log("Connecting plain connection");
return delegate.connectAsync()
return delegate.connectAsync(exchange)
.thenCompose(unused -> delegate.finishConnect())
.thenCompose((Void v) -> {
if (debug.on()) debug.log("sending HTTP/1.1 CONNECT");
HttpClientImpl client = client();
@ -70,7 +73,7 @@ final class PlainTunnelingConnection extends HttpConnection {
HttpRequestImpl req = new HttpRequestImpl("CONNECT", address, proxyHeaders);
MultiExchange<Void> mulEx = new MultiExchange<>(null, req,
client, discarding(), null, null);
Exchange<Void> connectExchange = new Exchange<>(req, mulEx);
Exchange<Void> connectExchange = mulEx.getExchange();
return connectExchange
.responseAsyncImpl(delegate)
@ -96,14 +99,36 @@ final class PlainTunnelingConnection extends HttpConnection {
ByteBuffer b = ((Http1Exchange<?>)connectExchange.exchImpl).drainLeftOverBytes();
int remaining = b.remaining();
assert remaining == 0: "Unexpected remaining: " + remaining;
connected = true;
cf.complete(null);
}
return cf;
});
})
.handle((result, ex) -> {
if (ex == null) {
return MinimalFuture.completedFuture(result);
} else {
if (debug.on())
debug.log("tunnel failed with \"%s\"", ex.toString());
Throwable t = ex;
if (t instanceof CompletionException)
t = t.getCause();
if (t instanceof HttpTimeoutException) {
String msg = "proxy tunneling CONNECT request timed out";
t = new HttpTimeoutException(msg);
t.initCause(ex);
}
return MinimalFuture.<Void>failedFuture(t);
}
})
.thenCompose(Function.identity());
});
}
public CompletableFuture<Void> finishConnect() {
connected = true;
return MinimalFuture.completedFuture(null);
}
@Override
boolean isTunnel() { return true; }

View File

@ -0,0 +1,78 @@
/*
* 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 jdk.internal.net.http;
import java.net.ConnectException;
import java.net.http.HttpConnectTimeoutException;
import java.net.http.HttpTimeoutException;
import jdk.internal.net.http.common.Logger;
import jdk.internal.net.http.common.Utils;
public class ResponseTimerEvent extends TimeoutEvent {
private static final Logger debug =
Utils.getDebugLogger("ResponseTimerEvent"::toString, Utils.DEBUG);
private final MultiExchange<?> multiExchange;
static ResponseTimerEvent of(MultiExchange<?> exchange) {
return new ResponseTimerEvent(exchange);
}
private ResponseTimerEvent(MultiExchange<?> multiExchange) {
super(multiExchange.exchange.request.timeout().get());
this.multiExchange = multiExchange;
}
@Override
public void handle() {
if (debug.on()) {
debug.log("Cancelling MultiExchange due to timeout for request %s",
multiExchange.exchange.request);
}
HttpTimeoutException t = null;
// more specific, "request timed out", message when connected
Exchange<?> exchange = multiExchange.getExchange();
if (exchange != null) {
ExchangeImpl<?> exchangeImpl = exchange.exchImpl;
if (exchangeImpl != null) {
if (exchangeImpl.connection().connected()) {
t = new HttpTimeoutException("request timed out");
}
}
}
if (t == null) {
t = new HttpConnectTimeoutException("HTTP connect timed out");
t.initCause(new ConnectException("HTTP connect timed out"));
}
multiExchange.cancel(t);
}
@Override
public String toString() {
return "ResponseTimerEvent[" + super.toString() + "]";
}
}

View File

@ -43,9 +43,11 @@ abstract class TimeoutEvent implements Comparable<TimeoutEvent> {
// we use id in compareTo to make compareTo consistent with equals
// see TimeoutEvent::compareTo below;
private final long id = COUNTER.incrementAndGet();
private final Duration duration;
private final Instant deadline;
TimeoutEvent(Duration duration) {
this.duration = duration;
deadline = Instant.now().plus(duration);
}
@ -75,6 +77,7 @@ abstract class TimeoutEvent implements Comparable<TimeoutEvent> {
@Override
public String toString() {
return "TimeoutEvent[id=" + id + ", deadline=" + deadline + "]";
return "TimeoutEvent[id=" + id + ", duration=" + duration
+ ", deadline=" + deadline + "]";
}
}

View File

@ -24,7 +24,7 @@
*/
/**
* Defines the core Java SE API.
* Defines the API of the Java SE Platform.
* <P>
*
* <dl>

View File

@ -98,42 +98,42 @@ doclet.Window_Help_title=API\u30D8\u30EB\u30D7
doclet.help.main_heading=API\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306E\u69CB\u6210
doclet.help.intro=\u3053\u306EAPI(Application Programming Interface)\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306B\u306F\u3001\u6B21\u306B\u8AAC\u660E\u3059\u308B\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3\u30FB\u30D0\u30FC\u306B\u3042\u308B\u9805\u76EE\u306B\u5BFE\u5FDC\u3059\u308B\u30DA\u30FC\u30B8\u304C\u542B\u307E\u308C\u307E\u3059\u3002
doclet.help.overview.modules.body=The {0} page is the front page of this API document and provides a list of all modules with a summary for each. This page can also contain an overall description of the set of modules.
doclet.help.overview.modules.body={0}\u30DA\u30FC\u30B8\u306FAPI\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306E\u30D5\u30ED\u30F3\u30C8\u30FB\u30DA\u30FC\u30B8\u3067\u3001\u5404\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u6982\u8981\u3092\u542B\u3080\u5168\u30E2\u30B8\u30E5\uFF0D\u30EB\u306E\u30EA\u30B9\u30C8\u304C\u8868\u793A\u3055\u308C\u307E\u3059\u3002\u4E00\u9023\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u6982\u8981\u8AAC\u660E\u3082\u8868\u793A\u3055\u308C\u307E\u3059\u3002
doclet.help.overview.packages.body={0}\u30DA\u30FC\u30B8\u306FAPI\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306E\u30D5\u30ED\u30F3\u30C8\u30FB\u30DA\u30FC\u30B8\u3067\u3001\u5404\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u6982\u8981\u3092\u542B\u3080\u5168\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u30EA\u30B9\u30C8\u304C\u8868\u793A\u3055\u308C\u307E\u3059\u3002\u4E00\u9023\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u6982\u8981\u8AAC\u660E\u3082\u8868\u793A\u3055\u308C\u307E\u3059\u3002
doclet.help.package.intro=Each package has a page that contains a list of its classes and interfaces, with a summary for each. These pages may contain six categories:
doclet.help.module.intro=Each module has a page that contains a list of its packages, dependencies on other modules, and services, with a summary for each. These page may contain three categories:
doclet.help.class_interface.head=Class or Interface
doclet.help.package.intro=\u5404\u30D1\u30C3\u30B1\u30FC\u30B8\u306B\u306F\u3001\u305D\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u30AF\u30E9\u30B9\u304A\u3088\u3073\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306E\u30EA\u30B9\u30C8\u3068\u3001\u305D\u308C\u305E\u308C\u306E\u6982\u8981\u3092\u542B\u3080\u30DA\u30FC\u30B8\u304C\u3042\u308A\u307E\u3059\u3002\u3053\u308C\u3089\u306E\u30DA\u30FC\u30B8\u306F6\u3064\u306E\u30AB\u30C6\u30B4\u30EA\u3067\u69CB\u6210\u3055\u308C\u307E\u3059\u3002
doclet.help.module.intro=\u5404\u30E2\u30B8\u30E5\u30FC\u30EB\u306B\u306F\u3001\u305D\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u3001\u4ED6\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u306B\u5BFE\u3059\u308B\u4F9D\u5B58\u6027\u3001\u304A\u3088\u3073\u30B5\u30FC\u30D3\u30B9\u306E\u30EA\u30B9\u30C8\u3068\u3001\u305D\u308C\u305E\u308C\u306E\u6982\u8981\u3092\u542B\u3080\u30DA\u30FC\u30B8\u304C\u3042\u308A\u307E\u3059\u3002\u3053\u308C\u3089\u306E\u30DA\u30FC\u30B8\u306F3\u3064\u306E\u30AB\u30C6\u30B4\u30EA\u3067\u69CB\u6210\u3055\u308C\u307E\u3059\u3002
doclet.help.class_interface.head=\u30AF\u30E9\u30B9\u307E\u305F\u306F\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9
doclet.help.class_interface.intro=\u5404\u30AF\u30E9\u30B9\u3001\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u3001\u30CD\u30B9\u30C8\u3055\u308C\u305F\u30AF\u30E9\u30B9\u304A\u3088\u3073\u30CD\u30B9\u30C8\u3055\u308C\u305F\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306B\u306F\u500B\u5225\u306E\u30DA\u30FC\u30B8\u304C\u3042\u308A\u307E\u3059\u3002\u5404\u30DA\u30FC\u30B8\u306B\u306F\u6B21\u306E\u3088\u3046\u306B\u3001\u30AF\u30E9\u30B9\u307E\u305F\u306F\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306E\u8AAC\u660E\u3068\u3001\u6982\u8981\u8868\u304A\u3088\u3073\u30E1\u30F3\u30D0\u30FC\u306E\u8A73\u7D30\u8AAC\u660E\u304C\u542B\u307E\u308C\u307E\u3059\u3002
doclet.help.class_interface.inheritance_diagram=Class Inheritance Diagram
doclet.help.class_interface.inheritance_diagram=\u30AF\u30E9\u30B9\u968E\u5C64\u8868\u793A
doclet.help.class_interface.subclasses=\u76F4\u7CFB\u306E\u30B5\u30D6\u30AF\u30E9\u30B9
doclet.help.class_interface.subinterfaces=\u65E2\u77E5\u306E\u30B5\u30D6\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306E\u30EA\u30B9\u30C8
doclet.help.class_interface.implementations=\u65E2\u77E5\u306E\u5B9F\u88C5\u30AF\u30E9\u30B9\u306E\u30EA\u30B9\u30C8
doclet.help.class_interface.declaration=Class or Interface Declaration
doclet.help.class_interface.description=Class or Interface Description
doclet.help.class_interface.declaration=\u30AF\u30E9\u30B9\u307E\u305F\u306F\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306E\u5BA3\u8A00
doclet.help.class_interface.description=\u30AF\u30E9\u30B9\u307E\u305F\u306F\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306E\u8AAC\u660E
doclet.help.class_interface.summary=\u5404\u6982\u8981\u30A8\u30F3\u30C8\u30EA\u306B\u306F\u3001\u305D\u306E\u9805\u76EE\u306E\u8A73\u7D30\u306A\u8AAC\u660E\u306E\u4E2D\u304B\u30891\u884C\u76EE\u306E\u6587\u304C\u8868\u793A\u3055\u308C\u307E\u3059\u3002\u8A73\u7D30\u306A\u8AAC\u660E\u306F\u30BD\u30FC\u30B9\u30FB\u30B3\u30FC\u30C9\u306B\u73FE\u308C\u308B\u9806\u306B\u4E26\u3079\u3089\u308C\u307E\u3059\u304C\u3001\u6982\u8981\u30A8\u30F3\u30C8\u30EA\u306F\u30A2\u30EB\u30D5\u30A1\u30D9\u30C3\u30C8\u9806\u306B\u4E26\u3079\u3089\u308C\u307E\u3059\u3002\u3053\u308C\u306B\u3088\u3063\u3066\u3001\u30D7\u30ED\u30B0\u30E9\u30DE\u304C\u8A2D\u5B9A\u3057\u305F\u8AD6\u7406\u7684\u306A\u30B0\u30EB\u30FC\u30D7\u5206\u3051\u304C\u4FDD\u6301\u3055\u308C\u307E\u3059\u3002
doclet.help.use.head=\u4F7F\u7528
doclet.help.use.body=Each documented package, class and interface has its own Use page. This page describes what packages, classes, methods, constructors and fields use any part of the given class or package. Given a class or interface A, its "Use" page includes subclasses of A, fields declared as A, methods that return A, and methods and constructors with parameters of type A. You can access this page by first going to the package, class or interface, then clicking on the "Use" link in the navigation bar.
doclet.help.use.body=\u5404\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u5316\u3055\u308C\u305F\u30D1\u30C3\u30B1\u30FC\u30B8\u3001\u30AF\u30E9\u30B9\u304A\u3088\u3073\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306B\u306F\u305D\u308C\u305E\u308C\u300C\u4F7F\u7528\u300D\u30DA\u30FC\u30B8\u304C\u3042\u308A\u307E\u3059\u3002\u3053\u306E\u30DA\u30FC\u30B8\u306B\u306F\u3001\u3069\u306E\u3088\u3046\u306A\u30D1\u30C3\u30B1\u30FC\u30B8\u3001\u30AF\u30E9\u30B9\u3001\u30E1\u30BD\u30C3\u30C9\u3001\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30BF\u304A\u3088\u3073\u30D5\u30A3\u30FC\u30EB\u30C9\u304C\u3001\u7279\u5B9A\u306E\u30AF\u30E9\u30B9\u307E\u305F\u306F\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u4E00\u90E8\u3092\u4F7F\u7528\u3057\u3066\u3044\u308B\u304B\u304C\u8A18\u8FF0\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u305F\u3068\u3048\u3070\u3001\u30AF\u30E9\u30B9A\u307E\u305F\u306F\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9A\u306E\u5834\u5408\u3001\u305D\u306E\u300C\u4F7F\u7528\u300D\u30DA\u30FC\u30B8\u306B\u306F\u3001A\u306E\u30B5\u30D6\u30AF\u30E9\u30B9\u3001A\u3068\u3057\u3066\u5BA3\u8A00\u3055\u308C\u308B\u30D5\u30A3\u30FC\u30EB\u30C9\u3001A\u3092\u8FD4\u3059\u30E1\u30BD\u30C3\u30C9\u3068\u3001\u578BA\u3092\u6301\u3064\u30E1\u30BD\u30C3\u30C9\u304A\u3088\u3073\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30BF\u304C\u542B\u307E\u308C\u307E\u3059\u3002\u3053\u306E\u30DA\u30FC\u30B8\u306B\u30A2\u30AF\u30BB\u30B9\u3059\u308B\u306B\u306F\u3001\u307E\u305A\u305D\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u3001\u30AF\u30E9\u30B9\u307E\u305F\u306F\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306B\u79FB\u52D5\u3057\u3001\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3\u30FB\u30D0\u30FC\u306E\u300C\u4F7F\u7528\u300D\u30EA\u30F3\u30AF\u3092\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u304F\u3060\u3055\u3044\u3002
doclet.help.tree.head=\u968E\u5C64\u30C4\u30EA\u30FC(\u30AF\u30E9\u30B9\u968E\u5C64)
doclet.help.tree.intro=There is a {0} page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. Classes are organized by inheritance structure starting with {1}. Interfaces do not inherit from {1}.
doclet.help.tree.intro=\u3059\u3079\u3066\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u306B\u306F{0}\u30DA\u30FC\u30B8\u304C\u3042\u308A\u3001\u3055\u3089\u306B\u5404\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u968E\u5C64\u304C\u3042\u308A\u307E\u3059\u3002\u5404\u968E\u5C64\u30DA\u30FC\u30B8\u306F\u3001\u30AF\u30E9\u30B9\u306E\u30EA\u30B9\u30C8\u3068\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306E\u30EA\u30B9\u30C8\u3092\u542B\u307F\u307E\u3059\u3002\u30AF\u30E9\u30B9\u306F{1}\u3092\u958B\u59CB\u70B9\u3068\u3059\u308B\u7D99\u627F\u69CB\u9020\u3067\u7DE8\u6210\u3055\u308C\u307E\u3059\u3002\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306F\u3001{1}\u304B\u3089\u306F\u7D99\u627F\u3057\u307E\u305B\u3093\u3002
doclet.help.tree.overview=\u6982\u8981\u30DA\u30FC\u30B8\u3092\u8868\u793A\u3057\u3066\u3044\u308B\u3068\u304D\u306B\u300C\u968E\u5C64\u30C4\u30EA\u30FC\u300D\u3092\u30AF\u30EA\u30C3\u30AF\u3059\u308B\u3068\u3001\u5168\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u968E\u5C64\u304C\u8868\u793A\u3055\u308C\u307E\u3059\u3002
doclet.help.tree.package=When viewing a particular package, class or interface page, clicking on "Tree" displays the hierarchy for only that package.
doclet.help.tree.package=\u7279\u5B9A\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u3001\u30AF\u30E9\u30B9\u307E\u305F\u306F\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306E\u30DA\u30FC\u30B8\u3092\u8868\u793A\u3057\u3066\u3044\u308B\u3068\u304D\u306B\u300C\u968E\u5C64\u30C4\u30EA\u30FC\u300D\u3092\u30AF\u30EA\u30C3\u30AF\u3059\u308B\u3068\u3001\u8A72\u5F53\u3059\u308B\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u307F\u306E\u968E\u5C64\u304C\u8868\u793A\u3055\u308C\u307E\u3059\u3002
doclet.help.deprecated.body={0}\u30DA\u30FC\u30B8\u306F\u3001\u63A8\u5968\u3055\u308C\u3066\u3044\u306A\u3044\u3059\u3079\u3066\u306EAPI\u306E\u30EA\u30B9\u30C8\u3092\u8868\u793A\u3057\u307E\u3059\u3002\u975E\u63A8\u5968API\u3068\u306F\u3001\u6A5F\u80FD\u6539\u826F\u306A\u3069\u306E\u7406\u7531\u304B\u3089\u4F7F\u7528\u3092\u304A\u85A6\u3081\u3067\u304D\u306A\u304F\u306A\u3063\u305FAPI\u306E\u3053\u3068\u3067\u3001\u901A\u5E38\u306F\u305D\u308C\u306B\u4EE3\u308F\u308BAPI\u304C\u63D0\u4F9B\u3055\u308C\u307E\u3059\u3002\u975E\u63A8\u5968API\u306F\u4ECA\u5F8C\u306E\u5B9F\u88C5\u3067\u524A\u9664\u3055\u308C\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002
doclet.help.index.head=\u7D22\u5F15
doclet.help.index.body=The {0} contains an alphabetic index of all classes, interfaces, constructors, methods, and fields, as well as lists of all packages and all classes.
doclet.help.index.body={0}\u306B\u306F\u3001\u3059\u3079\u3066\u306E\u30AF\u30E9\u30B9\u3001\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u3001\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30BF\u3001\u30E1\u30BD\u30C3\u30C9\u304A\u3088\u3073\u30D5\u30A3\u30FC\u30EB\u30C9\u306E\u30A2\u30EB\u30D5\u30A1\u30D9\u30C3\u30C8\u9806\u306E\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u3068\u3001\u3059\u3079\u3066\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u304A\u3088\u3073\u3059\u3079\u3066\u306E\u30AF\u30E9\u30B9\u306E\u30EA\u30B9\u30C8\u304C\u542B\u307E\u308C\u307E\u3059\u3002
doclet.help.frames.head=\u30D5\u30EC\u30FC\u30E0/\u30D5\u30EC\u30FC\u30E0\u306A\u3057
doclet.help.frames.body=\u3053\u308C\u3089\u306E\u30EA\u30F3\u30AF\u306FHTML\u30D5\u30EC\u30FC\u30E0\u306E\u8868\u793A\u3068\u975E\u8868\u793A\u3092\u5207\u308A\u66FF\u3048\u307E\u3059\u3002\u3059\u3079\u3066\u306E\u30DA\u30FC\u30B8\u306F\u30D5\u30EC\u30FC\u30E0\u3042\u308A\u3067\u3082\u3001\u30D5\u30EC\u30FC\u30E0\u306A\u3057\u3067\u3082\u8868\u793A\u3067\u304D\u307E\u3059\u3002
doclet.help.all_classes.body={0}\u30EA\u30F3\u30AF\u306B\u306F\u3001\u3059\u3079\u3066\u306E\u30AF\u30E9\u30B9\u304A\u3088\u3073\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9(\u975Estatic\u306E\u30CD\u30B9\u30C8\u3055\u308C\u305F\u578B\u3092\u9664\u304F)\u304C\u8868\u793A\u3055\u308C\u307E\u3059\u3002
doclet.help.serial_form.body=\u76F4\u5217\u5316\u53EF\u80FD\u307E\u305F\u306F\u5916\u90E8\u5316\u53EF\u80FD\u306A\u5404\u30AF\u30E9\u30B9\u306F\u3001\u76F4\u5217\u5316\u30D5\u30A3\u30FC\u30EB\u30C9\u3068\u30E1\u30BD\u30C3\u30C9\u306E\u8AAC\u660E\u3092\u542B\u307F\u307E\u3059\u3002\u3053\u306E\u60C5\u5831\u306F\u3001API\u3092\u4F7F\u7528\u3059\u308B\u958B\u767A\u8005\u3067\u306F\u306A\u304F\u3001\u518D\u5B9F\u88C5\u3092\u884C\u3046\u62C5\u5F53\u8005\u306B\u5F79\u7ACB\u3061\u307E\u3059\u3002\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3\u30FB\u30D0\u30FC\u306B\u30EA\u30F3\u30AF\u304C\u306A\u3044\u5834\u5408\u3001\u76F4\u5217\u5316\u3055\u308C\u305F\u30AF\u30E9\u30B9\u306B\u79FB\u52D5\u3057\u3066\u3001\u30AF\u30E9\u30B9\u8A18\u8FF0\u306E\u300C\u95A2\u9023\u9805\u76EE\u300D\u30BB\u30AF\u30B7\u30E7\u30F3\u306B\u3042\u308B\u300C\u76F4\u5217\u5316\u3055\u308C\u305F\u5F62\u5F0F\u300D\u3092\u30AF\u30EA\u30C3\u30AF\u3059\u308B\u3053\u3068\u306B\u3088\u308A\u3001\u3053\u306E\u60C5\u5831\u3092\u8868\u793A\u3067\u304D\u307E\u3059\u3002
doclet.help.constants.body={0}\u30DA\u30FC\u30B8\u306B\u306F\u3001static final\u30D5\u30A3\u30FC\u30EB\u30C9\u3068\u305D\u306E\u5024\u306E\u30EA\u30B9\u30C8\u304C\u3042\u308A\u307E\u3059\u3002
doclet.help.footnote=This help file applies to API documentation generated by the standard doclet.
doclet.help.footnote=\u3053\u306E\u30D8\u30EB\u30D7\u30FB\u30D5\u30A1\u30A4\u30EB\u306F\u3001\u6A19\u6E96doclet\u306B\u3088\u3063\u3066\u751F\u6210\u3055\u308C\u305FAPI\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306B\u9069\u7528\u3055\u308C\u307E\u3059\u3002
doclet.help.enum.intro=\u5404\u5217\u6319\u578B\u306B\u306F\u3001\u305D\u308C\u81EA\u8EAB\u306E\u500B\u5225\u306E\u30DA\u30FC\u30B8\u3068\u6B21\u306E\u30BB\u30AF\u30B7\u30E7\u30F3\u304C\u3042\u308A\u307E\u3059:
doclet.help.enum.declaration=\u5217\u6319\u5BA3\u8A00
doclet.help.enum.definition=Enum Description
doclet.help.enum.definition=\u5217\u6319\u578B\u306E\u8AAC\u660E
doclet.help.annotation_type.intro=\u5404\u6CE8\u91C8\u578B\u306B\u306F\u3001\u305D\u308C\u81EA\u8EAB\u306E\u500B\u5225\u306E\u30DA\u30FC\u30B8\u3068\u6B21\u306E\u30BB\u30AF\u30B7\u30E7\u30F3\u304C\u3042\u308A\u307E\u3059:
doclet.help.annotation_type.declaration=Annotation Type Declaration
doclet.help.annotation_type.description=Annotation Type Description
doclet.help.search.head=Search
doclet.help.search.body=You can search for definitions of modules, packages, types, fields, methods and other terms defined in the API, using some or all of the name. "Camel-case" abbreviations are supported: for example, "InpStr" will find "InputStream" and "InputStreamReader".
doclet.help.annotation_type.declaration=\u6CE8\u91C8\u578B\u306E\u5BA3\u8A00
doclet.help.annotation_type.description=\u6CE8\u91C8\u578B\u306E\u8AAC\u660E
doclet.help.search.head=\u691C\u7D22
doclet.help.search.body=\u30E2\u30B8\u30E5\u30FC\u30EB\u3001\u30D1\u30C3\u30B1\u30FC\u30B8\u3001\u30BF\u30A4\u30D7\u3001\u30D5\u30A3\u30FC\u30EB\u30C9\u3001\u30E1\u30BD\u30C3\u30C9\u3001\u304A\u3088\u3073API\u3067\u5B9A\u7FA9\u3055\u308C\u3066\u3044\u308B\u305D\u306E\u4ED6\u306E\u8A9E\u3092\u3001\u540D\u524D\u306E\u4E00\u90E8\u307E\u305F\u306F\u5168\u4F53\u3092\u4F7F\u7528\u3057\u3066\u691C\u7D22\u3067\u304D\u307E\u3059\u3002\u30AD\u30E3\u30E1\u30EB\u30B1\u30FC\u30B9\u306E\u7701\u7565\u5F62\u304C\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u3059: \u305F\u3068\u3048\u3070\u3001"InpStr"\u3068\u6307\u5B9A\u3059\u308B\u3068"InputStream"\u3068"InputStreamReader"\u304C\u691C\u7D22\u3055\u308C\u307E\u3059\u3002
doclet.ClassUse_Packages.that.use.0={0}\u3092\u4F7F\u7528\u3057\u3066\u3044\u308B\u30D1\u30C3\u30B1\u30FC\u30B8
doclet.ClassUse_Uses.of.0.in.1={1}\u3067\u306E{0}\u306E\u4F7F\u7528

View File

@ -98,42 +98,42 @@ doclet.Window_Help_title=API \u5E2E\u52A9
doclet.help.main_heading=\u6B64 API \u6587\u6863\u7684\u7EC4\u7EC7\u65B9\u5F0F
doclet.help.intro=\u6B64 API (\u5E94\u7528\u7A0B\u5E8F\u7F16\u7A0B\u63A5\u53E3) \u6587\u6863\u5305\u542B\u5BF9\u5E94\u4E8E\u5BFC\u822A\u680F\u4E2D\u7684\u9879\u76EE\u7684\u9875\u9762, \u5982\u4E0B\u6240\u8FF0\u3002
doclet.help.overview.modules.body=The {0} page is the front page of this API document and provides a list of all modules with a summary for each. This page can also contain an overall description of the set of modules.
doclet.help.overview.modules.body={0} \u9875\u662F\u6B64 API \u6587\u6863\u7684\u9996\u9875\uFF0C\u63D0\u4F9B\u4E86\u6240\u6709\u6A21\u5757\u7684\u5217\u8868\u53CA\u5176\u6982\u8981\u3002\u6B64\u9875\u4E5F\u53EF\u80FD\u5305\u542B\u8FD9\u4E9B\u6A21\u5757\u7684\u603B\u4F53\u8BF4\u660E\u3002
doclet.help.overview.packages.body={0} \u9875\u9762\u662F\u6B64 API \u6587\u6863\u7684\u9996\u9875, \u63D0\u4F9B\u4E86\u6240\u6709\u7A0B\u5E8F\u5305\u7684\u5217\u8868\u53CA\u5176\u6982\u8981\u3002\u6B64\u9875\u9762\u4E5F\u53EF\u80FD\u5305\u542B\u8FD9\u4E9B\u7A0B\u5E8F\u5305\u7684\u603B\u4F53\u8BF4\u660E\u3002
doclet.help.package.intro=Each package has a page that contains a list of its classes and interfaces, with a summary for each. These pages may contain six categories:
doclet.help.module.intro=Each module has a page that contains a list of its packages, dependencies on other modules, and services, with a summary for each. These page may contain three categories:
doclet.help.class_interface.head=Class or Interface
doclet.help.package.intro=\u6BCF\u4E2A\u7A0B\u5E8F\u5305\u90FD\u6709\u4E00\u9875\uFF0C\u5176\u4E2D\u5305\u542B\u5B83\u7684\u7C7B\u548C\u63A5\u53E3\u7684\u5217\u8868\u53CA\u5176\u6982\u8981\u3002\u8FD9\u4E9B\u9875\u53EF\u4EE5\u5305\u542B\u516D\u4E2A\u7C7B\u522B\uFF1A
doclet.help.module.intro=\u6BCF\u4E2A\u6A21\u5757\u90FD\u6709\u4E00\u9875\uFF0C\u5176\u4E2D\u5305\u542B\u5B83\u7684\u7A0B\u5E8F\u5305\u3001\u4E0E\u5176\u4ED6\u6A21\u5757\u7684\u4F9D\u8D56\u5173\u7CFB\u548C\u670D\u52A1\u7684\u5217\u8868\u4EE5\u53CA\u5404\u4E2A\u6A21\u5757\u7684\u6982\u8981\u3002\u8FD9\u4E9B\u9875\u53EF\u4EE5\u5305\u542B\u4E09\u4E2A\u7C7B\u522B\uFF1A
doclet.help.class_interface.head=\u7C7B\u6216\u63A5\u53E3
doclet.help.class_interface.intro=\u6BCF\u4E2A\u7C7B, \u63A5\u53E3, \u5D4C\u5957\u7C7B\u548C\u5D4C\u5957\u63A5\u53E3\u90FD\u6709\u5404\u81EA\u7684\u9875\u9762\u3002\u5176\u4E2D\u6BCF\u4E2A\u9875\u9762\u90FD\u7531\u4E09\u90E8\u5206 (\u7C7B/\u63A5\u53E3\u8BF4\u660E, \u6982\u8981\u8868, \u4EE5\u53CA\u8BE6\u7EC6\u7684\u6210\u5458\u8BF4\u660E) \u7EC4\u6210:
doclet.help.class_interface.inheritance_diagram=Class Inheritance Diagram
doclet.help.class_interface.inheritance_diagram=\u7C7B\u7EE7\u627F\u56FE
doclet.help.class_interface.subclasses=\u76F4\u63A5\u5B50\u7C7B
doclet.help.class_interface.subinterfaces=\u6240\u6709\u5DF2\u77E5\u5B50\u63A5\u53E3
doclet.help.class_interface.implementations=\u6240\u6709\u5DF2\u77E5\u5B9E\u73B0\u7C7B
doclet.help.class_interface.declaration=Class or Interface Declaration
doclet.help.class_interface.description=Class or Interface Description
doclet.help.class_interface.declaration=\u7C7B\u6216\u63A5\u53E3\u58F0\u660E
doclet.help.class_interface.description=\u7C7B\u6216\u63A5\u53E3\u8BF4\u660E
doclet.help.class_interface.summary=\u6BCF\u4E2A\u6982\u8981\u6761\u76EE\u90FD\u5305\u542B\u8BE5\u9879\u76EE\u7684\u8BE6\u7EC6\u8BF4\u660E\u7684\u7B2C\u4E00\u53E5\u3002\u6982\u8981\u6761\u76EE\u6309\u5B57\u6BCD\u987A\u5E8F\u6392\u5217, \u800C\u8BE6\u7EC6\u8BF4\u660E\u5219\u6309\u5176\u5728\u6E90\u4EE3\u7801\u4E2D\u51FA\u73B0\u7684\u987A\u5E8F\u6392\u5217\u3002\u8FD9\u6837\u4FDD\u6301\u4E86\u7A0B\u5E8F\u5458\u6240\u5EFA\u7ACB\u7684\u903B\u8F91\u5206\u7EC4\u3002
doclet.help.use.head=\u4F7F\u7528
doclet.help.use.body=Each documented package, class and interface has its own Use page. This page describes what packages, classes, methods, constructors and fields use any part of the given class or package. Given a class or interface A, its "Use" page includes subclasses of A, fields declared as A, methods that return A, and methods and constructors with parameters of type A. You can access this page by first going to the package, class or interface, then clicking on the "Use" link in the navigation bar.
doclet.help.use.body=\u6BCF\u4E2A\u5DF2\u6587\u6863\u5316\u7684\u7A0B\u5E8F\u5305\u3001\u7C7B\u548C\u63A5\u53E3\u90FD\u6709\u5404\u81EA\u7684\u201C\u4F7F\u7528\u201D\u9875\u3002\u6B64\u9875\u4ECB\u7ECD\u4E86\u4F7F\u7528\u7ED9\u5B9A\u7C7B\u6216\u7A0B\u5E8F\u5305\u7684\u4EFB\u4F55\u90E8\u5206\u7684\u7A0B\u5E8F\u5305\u3001\u7C7B\u3001\u65B9\u6CD5\u3001\u6784\u9020\u5668\u548C\u5B57\u6BB5\u3002\u5BF9\u4E8E\u7ED9\u5B9A\u7684\u7C7B\u6216\u63A5\u53E3 A\uFF0C\u5176\u201C\u4F7F\u7528\u201D\u9875\u5305\u542B A \u7684\u5B50\u7C7B\u3001\u58F0\u660E\u4E3A A \u7684\u5B57\u6BB5\u3001\u8FD4\u56DE A \u7684\u65B9\u6CD5\u4EE5\u53CA\u5E26\u6709\u7C7B\u578B\u4E3A A \u7684\u53C2\u6570\u7684\u65B9\u6CD5\u548C\u6784\u9020\u5668\u3002\u8BBF\u95EE\u6B64\u9875\u7684\u65B9\u6CD5\u662F\uFF1A\u9996\u5148\u8F6C\u81F3\u7A0B\u5E8F\u5305\u3001\u7C7B\u6216\u63A5\u53E3\uFF0C\u7136\u540E\u5355\u51FB\u5BFC\u822A\u680F\u4E2D\u7684\u201C\u4F7F\u7528\u201D\u94FE\u63A5\u3002
doclet.help.tree.head=\u6811 (\u7C7B\u5206\u5C42\u7ED3\u6784)
doclet.help.tree.intro=There is a {0} page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. Classes are organized by inheritance structure starting with {1}. Interfaces do not inherit from {1}.
doclet.help.tree.intro=\u5BF9\u4E8E\u6240\u6709\u7A0B\u5E8F\u5305\uFF0C\u90FD\u6709\u4E00\u4E2A {0} \u9875\uFF0C\u4EE5\u53CA\u6BCF\u4E2A\u7A0B\u5E8F\u5305\u7684\u5206\u5C42\u7ED3\u6784\u3002\u6BCF\u4E2A\u5206\u5C42\u7ED3\u6784\u9875\u90FD\u5305\u542B\u7C7B\u7684\u5217\u8868\u548C\u63A5\u53E3\u7684\u5217\u8868\u3002\u4ECE {1} \u5F00\u59CB\uFF0C\u6309\u7EE7\u627F\u7ED3\u6784\u5BF9\u7C7B\u8FDB\u884C\u6392\u5217\u3002\u63A5\u53E3\u4E0D\u4ECE {1} \u7EE7\u627F\u3002
doclet.help.tree.overview=\u67E5\u770B\u201C\u6982\u89C8\u201D\u9875\u9762\u65F6, \u5355\u51FB "\u6811" \u5C06\u663E\u793A\u6240\u6709\u7A0B\u5E8F\u5305\u7684\u5206\u5C42\u7ED3\u6784\u3002
doclet.help.tree.package=When viewing a particular package, class or interface page, clicking on "Tree" displays the hierarchy for only that package.
doclet.help.tree.package=\u67E5\u770B\u7279\u5B9A\u7A0B\u5E8F\u5305\u3001\u7C7B\u6216\u63A5\u53E3\u9875\u65F6\uFF0C\u5355\u51FB\u201C\u6811\u201D\u5C06\u4EC5\u663E\u793A\u8BE5\u7A0B\u5E8F\u5305\u7684\u5206\u5C42\u7ED3\u6784\u3002
doclet.help.deprecated.body={0} \u9875\u9762\u5217\u51FA\u4E86\u6240\u6709\u5DF2\u8FC7\u65F6\u7684 API\u3002\u4E00\u822C\u7531\u4E8E\u8FDB\u884C\u4E86\u6539\u8FDB\u5E76\u4E14\u901A\u5E38\u63D0\u4F9B\u4E86\u66FF\u4EE3\u7684 API, \u6240\u4EE5\u5EFA\u8BAE\u4E0D\u8981\u4F7F\u7528\u5DF2\u8FC7\u65F6\u7684 API\u3002\u5728\u5C06\u6765\u7684\u5B9E\u73B0\u8FC7\u7A0B\u4E2D, \u53EF\u80FD\u4F1A\u5220\u9664\u5DF2\u8FC7\u65F6\u7684 API\u3002
doclet.help.index.head=\u7D22\u5F15
doclet.help.index.body=The {0} contains an alphabetic index of all classes, interfaces, constructors, methods, and fields, as well as lists of all packages and all classes.
doclet.help.index.body={0} \u5305\u542B\u6240\u6709\u7C7B\u3001\u63A5\u53E3\u3001\u6784\u9020\u5668\u3001\u65B9\u6CD5\u548C\u5B57\u6BB5\u7684\u6309\u5B57\u6BCD\u987A\u5E8F\u6392\u5217\u7684\u7D22\u5F15\uFF0C\u4EE5\u53CA\u6240\u6709\u7A0B\u5E8F\u5305\u548C\u6240\u6709\u7C7B\u7684\u5217\u8868\u3002
doclet.help.frames.head=\u6846\u67B6/\u65E0\u6846\u67B6
doclet.help.frames.body=\u8FD9\u4E9B\u94FE\u63A5\u7528\u4E8E\u663E\u793A\u548C\u9690\u85CF HTML \u6846\u67B6\u3002\u6240\u6709\u9875\u9762\u5747\u5177\u6709\u6709\u6846\u67B6\u548C\u65E0\u6846\u67B6\u4E24\u79CD\u663E\u793A\u65B9\u5F0F\u3002
doclet.help.all_classes.body={0}\u94FE\u63A5\u663E\u793A\u6240\u6709\u7C7B\u548C\u63A5\u53E3 (\u9664\u4E86\u975E\u9759\u6001\u5D4C\u5957\u7C7B\u578B)\u3002
doclet.help.serial_form.body=\u6BCF\u4E2A\u53EF\u5E8F\u5217\u5316\u6216\u53EF\u5916\u90E8\u5316\u7684\u7C7B\u90FD\u6709\u5176\u5E8F\u5217\u5316\u5B57\u6BB5\u548C\u65B9\u6CD5\u7684\u8BF4\u660E\u3002\u6B64\u4FE1\u606F\u5BF9\u91CD\u65B0\u5B9E\u73B0\u8005\u6709\u7528, \u800C\u5BF9\u4F7F\u7528 API \u7684\u5F00\u53D1\u8005\u5219\u6CA1\u6709\u4EC0\u4E48\u7528\u5904\u3002\u5C3D\u7BA1\u5BFC\u822A\u680F\u4E2D\u6CA1\u6709\u94FE\u63A5, \u4F46\u60A8\u53EF\u4EE5\u901A\u8FC7\u4E0B\u5217\u65B9\u5F0F\u83B7\u53D6\u6B64\u4FE1\u606F: \u8F6C\u81F3\u4EFB\u4F55\u5E8F\u5217\u5316\u7C7B, \u7136\u540E\u5355\u51FB\u7C7B\u8BF4\u660E\u7684 "\u53E6\u8BF7\u53C2\u9605" \u90E8\u5206\u4E2D\u7684 "\u5E8F\u5217\u5316\u8868\u683C"\u3002
doclet.help.constants.body={0}\u9875\u9762\u5217\u51FA\u4E86\u9759\u6001\u6700\u7EC8\u5B57\u6BB5\u53CA\u5176\u503C\u3002
doclet.help.footnote=This help file applies to API documentation generated by the standard doclet.
doclet.help.footnote=\u6B64\u5E2E\u52A9\u6587\u4EF6\u9002\u7528\u4E8E\u7531\u6807\u51C6 doclet \u751F\u6210\u7684 API \u6587\u6863\u3002
doclet.help.enum.intro=\u6BCF\u4E2A\u679A\u4E3E\u90FD\u6709\u5404\u81EA\u7684\u9875\u9762, \u5176\u4E2D\u5305\u542B\u4EE5\u4E0B\u90E8\u5206:
doclet.help.enum.declaration=\u679A\u4E3E\u58F0\u660E
doclet.help.enum.definition=Enum Description
doclet.help.enum.definition=\u679A\u4E3E\u8BF4\u660E
doclet.help.annotation_type.intro=\u6BCF\u4E2A\u6CE8\u91CA\u7C7B\u578B\u90FD\u6709\u5404\u81EA\u7684\u9875\u9762, \u5176\u4E2D\u5305\u542B\u4EE5\u4E0B\u90E8\u5206:
doclet.help.annotation_type.declaration=Annotation Type Declaration
doclet.help.annotation_type.description=Annotation Type Description
doclet.help.search.head=Search
doclet.help.search.body=You can search for definitions of modules, packages, types, fields, methods and other terms defined in the API, using some or all of the name. "Camel-case" abbreviations are supported: for example, "InpStr" will find "InputStream" and "InputStreamReader".
doclet.help.annotation_type.declaration=\u6CE8\u91CA\u7C7B\u578B\u58F0\u660E
doclet.help.annotation_type.description=\u6CE8\u91CA\u7C7B\u578B\u8BF4\u660E
doclet.help.search.head=\u641C\u7D22
doclet.help.search.body=\u53EF\u4EE5\u4F7F\u7528\u90E8\u5206\u6216\u5B8C\u6574\u540D\u79F0\u641C\u7D22\u6A21\u5757\u3001\u7A0B\u5E8F\u5305\u3001\u7C7B\u578B\u3001\u5B57\u6BB5\u3001\u65B9\u6CD5\u4EE5\u53CA\u5728 API \u4E2D\u5B9A\u4E49\u7684\u5176\u4ED6\u672F\u8BED\u7684\u5B9A\u4E49\u3002\u652F\u6301\u201C\u9A7C\u5CF0\u5927\u5C0F\u5199\u5F0F\u201D\u7F29\u5199\uFF1A\u4F8B\u5982\uFF0C"InpStr" \u5C06\u67E5\u627E "InputStream" \u548C "InputStreamReader"\u3002
doclet.ClassUse_Packages.that.use.0=\u4F7F\u7528{0}\u7684\u7A0B\u5E8F\u5305
doclet.ClassUse_Uses.of.0.in.1={1}\u4E2D{0}\u7684\u4F7F\u7528

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,42 @@
/*
* 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.
*
* 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.
*/
/*
* @test
* @bug 8207355
* @compile TestLinearScanOrder.jasm
* @run main/othervm -Xcomp -XX:+TieredCompilation -XX:TieredStopAtLevel=1
* -XX:CompileCommand=compileonly,compiler.c1.TestLinearScanOrder::test
* compiler.c1.TestLinearScanOrderMain
*/
package compiler.c1;
// WARNING: This test will not fail but time out in C1's ComputeLinearScanOrder phase
public class TestLinearScanOrderMain {
public static void main(String[] args) {
if (TestLinearScanOrder.test() != 42) {
throw new RuntimeException("Test failed");
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 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
@ -21,12 +21,6 @@
* questions.
*
*/
super class compiler/linkage/I
version 52:0
{
}
super class compiler/linkage/CallSites
version 52:0

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 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
@ -54,11 +54,24 @@ class X {
public class LinkageErrors {
final static MethodHandles.Lookup L = MethodHandles.lookup();
static void test(MethodHandle mh) {
static void testICCE(MethodHandle mh) {
try {
mh.invokeExact();
throw new AssertionError("No exception thrown");
} catch (LinkageError e) {
} catch (IncompatibleClassChangeError e) {
return; // expected
} catch (AssertionError e) {
throw e; // rethrow
} catch (Throwable e) {
throw new AssertionError("Unexpected exception", e);
}
}
static void testNSME(MethodHandle mh) {
try {
mh.invokeExact();
throw new AssertionError("No exception thrown");
} catch (NoSuchMethodError e) {
return; // expected
} catch (AssertionError e) {
throw e; // rethrow
@ -93,18 +106,18 @@ public class LinkageErrors {
MethodHandle testX3_null = testX3.bindTo(null);
for (int i = 0; i < 20_000; i++) {
test(testI1_A);
test(testI1_null);
test(testX1_X);
test(testX1_null);
testNSME(testI1_A);
testNSME(testI1_null);
testNSME(testX1_X);
testNSME(testX1_null);
test(testI2);
test(testX2);
testICCE(testI2);
testICCE(testX2);
test(testI3_A);
test(testI3_null);
test(testX3_X);
test(testX3_null);
testICCE(testI3_A);
testICCE(testI3_null);
testICCE(testX3_X);
testICCE(testX3_null);
}
System.out.println("TEST PASSED");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 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
@ -85,8 +85,8 @@ public abstract class CompilerWhiteBoxTest {
BACKEDGE_THRESHOLD = THRESHOLD = 150000;
} else {
THRESHOLD = COMPILE_THRESHOLD;
BACKEDGE_THRESHOLD = COMPILE_THRESHOLD * Long.parseLong(getVMOption(
"OnStackReplacePercentage"));
BACKEDGE_THRESHOLD = Math.max(10000, COMPILE_THRESHOLD *
Long.parseLong(getVMOption("OnStackReplacePercentage")));
}
}

View File

@ -25,10 +25,12 @@
* @test
* @library /test/lib
* @build jdk.test.lib.Utils
* @bug 8204233 8207846
* @bug 8204233 8207846 8208691
* @summary Add configurable option for enhanced socket IOException messages
* @run main/othervm
* ExceptionText
* @run main/othervm
* ExceptionText
* WITHOUT_Enhanced_Text
* @run main/othervm
* -Djdk.includeInExceptions=
@ -62,6 +64,7 @@ import java.net.Socket;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SocketChannel;
import java.security.Security;
import java.util.concurrent.ExecutionException;
import jdk.test.lib.Utils;
@ -70,20 +73,33 @@ public class ExceptionText {
enum TestTarget {SOCKET, CHANNEL, ASYNC_CHANNEL};
public static void main(String args[]) throws Exception {
String passOrFail = args[0];
boolean expectEnhancedText;
if (passOrFail.equals("expectEnhancedText")) {
expectEnhancedText = true;
if (args.length == 0) {
testSecProp();
} else {
expectEnhancedText = false;
String passOrFail = args[0];
boolean expectEnhancedText;
if (passOrFail.equals("expectEnhancedText")) {
expectEnhancedText = true;
} else {
expectEnhancedText = false;
}
test(expectEnhancedText);
}
test(expectEnhancedText);
}
static final InetSocketAddress dest = Utils.refusingEndpoint();
static final String PORT = ":" + Integer.toString(dest.getPort());
static final String HOST = dest.getHostString();
static void testSecProp() {
String incInExc = Security.getProperty("jdk.includeInExceptions");
if (incInExc != null) {
throw new RuntimeException("Test failed: default value of " +
"jdk.includeInExceptions security property is not null: " +
incInExc);
}
}
static void test(boolean withProperty) {
// Socket
IOException e = getException(TestTarget.SOCKET);

View File

@ -0,0 +1,257 @@
/*
* 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.
*
* 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.
*/
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.NoRouteToHostException;
import java.net.ProxySelector;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Version;
import java.net.http.HttpConnectTimeoutException;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletionException;
import org.testng.annotations.DataProvider;
import static java.lang.System.out;
import static java.net.http.HttpClient.Builder.NO_PROXY;
import static java.net.http.HttpClient.Version.HTTP_1_1;
import static java.net.http.HttpClient.Version.HTTP_2;
import static java.time.Duration.*;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static org.testng.Assert.fail;
public abstract class AbstractConnectTimeout {
static final Duration NO_DURATION = null;
static List<List<Duration>> TIMEOUTS = List.of(
// connectTimeout HttpRequest timeout
Arrays.asList( NO_DURATION, ofSeconds(1) ),
Arrays.asList( NO_DURATION, ofMillis(100) ),
Arrays.asList( NO_DURATION, ofNanos(99) ),
Arrays.asList( NO_DURATION, ofNanos(1) ),
Arrays.asList( ofSeconds(1), NO_DURATION ),
Arrays.asList( ofMillis(100), NO_DURATION ),
Arrays.asList( ofNanos(99), NO_DURATION ),
Arrays.asList( ofNanos(1), NO_DURATION ),
Arrays.asList( ofSeconds(1), ofMinutes(1) ),
Arrays.asList( ofMillis(100), ofMinutes(1) ),
Arrays.asList( ofNanos(99), ofMinutes(1) ),
Arrays.asList( ofNanos(1), ofMinutes(1) )
);
static final List<String> METHODS = List.of("GET", "POST");
static final List<Version> VERSIONS = List.of(HTTP_2, HTTP_1_1);
static final List<String> SCHEMES = List.of("https", "http");
@DataProvider(name = "variants")
public Object[][] variants() {
List<Object[]> l = new ArrayList<>();
for (List<Duration> timeouts : TIMEOUTS) {
Duration connectTimeout = timeouts.get(0);
Duration requestTimeout = timeouts.get(1);
for (String method: METHODS) {
for (String scheme : SCHEMES) {
for (Version requestVersion : VERSIONS) {
l.add(new Object[] {requestVersion, scheme, method, connectTimeout, requestTimeout});
}}}}
return l.stream().toArray(Object[][]::new);
}
static final ProxySelector EXAMPLE_DOT_COM_PROXY = ProxySelector.of(
InetSocketAddress.createUnresolved("example.com", 8080));
//@Test(dataProvider = "variants")
protected void timeoutNoProxySync(Version requestVersion,
String scheme,
String method,
Duration connectTimeout,
Duration requestTimeout)
throws Exception
{
timeoutSync(requestVersion, scheme, method, connectTimeout, requestTimeout, NO_PROXY);
}
//@Test(dataProvider = "variants")
protected void timeoutWithProxySync(Version requestVersion,
String scheme,
String method,
Duration connectTimeout,
Duration requestTimeout)
throws Exception
{
timeoutSync(requestVersion, scheme, method, connectTimeout, requestTimeout, EXAMPLE_DOT_COM_PROXY);
}
private void timeoutSync(Version requestVersion,
String scheme,
String method,
Duration connectTimeout,
Duration requestTimeout,
ProxySelector proxy)
throws Exception
{
out.printf("%ntimeoutSync(requestVersion=%s, scheme=%s, method=%s,"
+ " connectTimeout=%s, requestTimeout=%s, proxy=%s)%n",
requestVersion, scheme, method, connectTimeout, requestTimeout, proxy);
HttpClient client = newClient(connectTimeout, proxy);
HttpRequest request = newRequest(scheme, requestVersion, method, requestTimeout);
for (int i = 0; i < 2; i++) {
out.printf("iteration %d%n", i);
long startTime = System.nanoTime();
try {
HttpResponse<?> resp = client.send(request, BodyHandlers.ofString());
printResponse(resp);
fail("Unexpected response: " + resp);
} catch (HttpConnectTimeoutException expected) { // blocking thread-specific exception
long elapsedTime = NANOSECONDS.toMillis(System.nanoTime() - startTime);
out.printf("Client: received in %d millis%n", elapsedTime);
assertExceptionTypeAndCause(expected.getCause());
} catch (ConnectException e) {
long elapsedTime = NANOSECONDS.toMillis(System.nanoTime() - startTime);
out.printf("Client: received in %d millis%n", elapsedTime);
Throwable t = e.getCause().getCause(); // blocking thread-specific exception
if (!(t instanceof NoRouteToHostException)) { // tolerate only NRTHE
e.printStackTrace(out);
fail("Unexpected exception:" + e);
} else {
out.printf("Caught ConnectException with NoRouteToHostException"
+ " cause: %s - skipping%n", t.getCause());
}
}
}
}
//@Test(dataProvider = "variants")
protected void timeoutNoProxyAsync(Version requestVersion,
String scheme,
String method,
Duration connectTimeout,
Duration requestTimeout) {
timeoutAsync(requestVersion, scheme, method, connectTimeout, requestTimeout, NO_PROXY);
}
//@Test(dataProvider = "variants")
protected void timeoutWithProxyAsync(Version requestVersion,
String scheme,
String method,
Duration connectTimeout,
Duration requestTimeout) {
timeoutAsync(requestVersion, scheme, method, connectTimeout, requestTimeout, EXAMPLE_DOT_COM_PROXY);
}
private void timeoutAsync(Version requestVersion,
String scheme,
String method,
Duration connectTimeout,
Duration requestTimeout,
ProxySelector proxy) {
out.printf("%ntimeoutAsync(requestVersion=%s, scheme=%s, method=%s, "
+ "connectTimeout=%s, requestTimeout=%s, proxy=%s)%n",
requestVersion, scheme, method, connectTimeout, requestTimeout, proxy);
HttpClient client = newClient(connectTimeout, proxy);
HttpRequest request = newRequest(scheme, requestVersion, method, requestTimeout);
for (int i = 0; i < 2; i++) {
out.printf("iteration %d%n", i);
long startTime = System.nanoTime();
try {
HttpResponse<?> resp = client.sendAsync(request, BodyHandlers.ofString()).join();
printResponse(resp);
fail("Unexpected response: " + resp);
} catch (CompletionException e) {
long elapsedTime = NANOSECONDS.toMillis(System.nanoTime() - startTime);
out.printf("Client: received in %d millis%n", elapsedTime);
Throwable t = e.getCause();
if (t instanceof ConnectException &&
t.getCause() instanceof NoRouteToHostException) { // tolerate only NRTHE
out.printf("Caught ConnectException with NoRouteToHostException"
+ " cause: %s - skipping%n", t.getCause());
} else {
assertExceptionTypeAndCause(t);
}
}
}
}
static HttpClient newClient(Duration connectTimeout, ProxySelector proxy) {
HttpClient.Builder builder = HttpClient.newBuilder().proxy(proxy);
if (connectTimeout != NO_DURATION)
builder.connectTimeout(connectTimeout);
return builder.build();
}
static HttpRequest newRequest(String scheme,
Version reqVersion,
String method,
Duration requestTimeout) {
// Resolvable address. Most tested environments just ignore the TCP SYN,
// or occasionally return ICMP no route to host
URI uri = URI.create(scheme +"://example.com:81/");
HttpRequest.Builder reqBuilder = HttpRequest.newBuilder(uri);
reqBuilder = reqBuilder.version(reqVersion);
switch (method) {
case "GET" : reqBuilder.GET(); break;
case "POST" : reqBuilder.POST(BodyPublishers.noBody()); break;
default: throw new AssertionError("Unknown method:" + method);
}
if (requestTimeout != NO_DURATION)
reqBuilder.timeout(requestTimeout);
return reqBuilder.build();
}
static void assertExceptionTypeAndCause(Throwable t) {
if (!(t instanceof HttpConnectTimeoutException)) {
t.printStackTrace(out);
fail("Expected HttpConnectTimeoutException, got:" + t);
}
Throwable connEx = t.getCause();
if (!(connEx instanceof ConnectException)) {
t.printStackTrace(out);
fail("Expected ConnectException cause in:" + connEx);
}
out.printf("Caught expected HttpConnectTimeoutException with ConnectException"
+ " cause: %n%s%n%s%n", t, connEx);
final String EXPECTED_MESSAGE = "HTTP connect timed out"; // impl dependent
if (!connEx.getMessage().equals(EXPECTED_MESSAGE))
fail("Expected: \"" + EXPECTED_MESSAGE + "\", got: \"" + connEx.getMessage() + "\"");
}
static void printResponse(HttpResponse<?> response) {
out.println("Unexpected response: " + response);
out.println("Headers: " + response.headers());
out.println("Body: " + response.body());
}
}

View File

@ -0,0 +1,288 @@
/*
* 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.
*
* 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.
*/
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URI;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Version;
import java.net.http.HttpConnectTimeoutException;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import static java.lang.String.format;
import static java.lang.System.out;
import static java.net.http.HttpClient.Builder.NO_PROXY;
import static java.net.http.HttpClient.Version.HTTP_1_1;
import static java.net.http.HttpClient.Version.HTTP_2;
import static java.time.Duration.*;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static org.testng.Assert.fail;
public abstract class AbstractConnectTimeoutHandshake {
// The number of iterations each testXXXClient performs.
static final int TIMES = 2;
Server server;
URI httpsURI;
static final Duration NO_DURATION = null;
static List<List<Duration>> TIMEOUTS = List.of(
// connectTimeout HttpRequest timeout
Arrays.asList( NO_DURATION, ofSeconds(1) ),
Arrays.asList( NO_DURATION, ofSeconds(2) ),
Arrays.asList( NO_DURATION, ofMillis(500) ),
Arrays.asList( ofSeconds(1), NO_DURATION ),
Arrays.asList( ofSeconds(2), NO_DURATION ),
Arrays.asList( ofMillis(500), NO_DURATION ),
Arrays.asList( ofSeconds(1), ofMinutes(1) ),
Arrays.asList( ofSeconds(2), ofMinutes(1) ),
Arrays.asList( ofMillis(500), ofMinutes(1) )
);
static final List<String> METHODS = List.of("GET" , "POST");
static final List<Version> VERSIONS = List.of(HTTP_2, HTTP_1_1);
@DataProvider(name = "variants")
public Object[][] variants() {
List<Object[]> l = new ArrayList<>();
for (List<Duration> timeouts : TIMEOUTS) {
Duration connectTimeout = timeouts.get(0);
Duration requestTimeout = timeouts.get(1);
for (String method: METHODS) {
for (Version requestVersion : VERSIONS) {
l.add(new Object[] {requestVersion, method, connectTimeout, requestTimeout});
}}}
return l.stream().toArray(Object[][]::new);
}
//@Test(dataProvider = "variants")
protected void timeoutSync(Version requestVersion,
String method,
Duration connectTimeout,
Duration requestTimeout)
throws Exception
{
out.printf("%n--- timeoutSync requestVersion=%s, method=%s, "
+ "connectTimeout=%s, requestTimeout=%s ---%n",
requestVersion, method, connectTimeout, requestTimeout);
HttpClient client = newClient(connectTimeout);
HttpRequest request = newRequest(requestVersion, method, requestTimeout);
for (int i = 0; i < TIMES; i++) {
out.printf("iteration %d%n", i);
long startTime = System.nanoTime();
try {
HttpResponse<String> resp = client.send(request, BodyHandlers.ofString());
printResponse(resp);
fail("Unexpected response: " + resp);
} catch (HttpConnectTimeoutException expected) {
long elapsedTime = NANOSECONDS.toMillis(System.nanoTime() - startTime);
out.printf("Client: received in %d millis%n", elapsedTime);
out.printf("Client: caught expected HttpConnectTimeoutException: %s%n", expected);
checkExceptionOrCause(ConnectException.class, expected);
}
}
}
//@Test(dataProvider = "variants")
protected void timeoutAsync(Version requestVersion,
String method,
Duration connectTimeout,
Duration requestTimeout) {
out.printf("%n--- timeoutAsync requestVersion=%s, method=%s, "
+ "connectTimeout=%s, requestTimeout=%s ---%n",
requestVersion, method, connectTimeout, requestTimeout);
HttpClient client = newClient(connectTimeout);
HttpRequest request = newRequest(requestVersion, method, requestTimeout);
for (int i = 0; i < TIMES; i++) {
out.printf("iteration %d%n", i);
long startTime = System.nanoTime();
CompletableFuture<HttpResponse<String>> cf =
client.sendAsync(request, BodyHandlers.ofString());
try {
HttpResponse<String> resp = cf.join();
printResponse(resp);
fail("Unexpected response: " + resp);
} catch (CompletionException ce) {
long elapsedTime = NANOSECONDS.toMillis(System.nanoTime() - startTime);
out.printf("Client: received in %d millis%n", elapsedTime);
Throwable expected = ce.getCause();
if (expected instanceof HttpConnectTimeoutException) {
out.printf("Client: caught expected HttpConnectTimeoutException: %s%n", expected);
checkExceptionOrCause(ConnectException.class, expected);
} else {
out.printf("Client: caught UNEXPECTED exception: %s%n", expected);
throw ce;
}
}
}
}
static HttpClient newClient(Duration connectTimeout) {
HttpClient.Builder builder = HttpClient.newBuilder().proxy(NO_PROXY);
if (connectTimeout != NO_DURATION)
builder.connectTimeout(connectTimeout);
return builder.build();
}
HttpRequest newRequest(Version reqVersion,
String method,
Duration requestTimeout) {
HttpRequest.Builder reqBuilder = HttpRequest.newBuilder(httpsURI);
reqBuilder = reqBuilder.version(reqVersion);
switch (method) {
case "GET" : reqBuilder.GET(); break;
case "POST" : reqBuilder.POST(BodyPublishers.noBody()); break;
default: throw new AssertionError("Unknown method:" + method);
}
if (requestTimeout != NO_DURATION)
reqBuilder.timeout(requestTimeout);
return reqBuilder.build();
}
static void checkExceptionOrCause(Class<? extends Throwable> clazz, Throwable t) {
final Throwable original = t;
do {
if (clazz.isInstance(t)) {
System.out.println("Found expected exception/cause: " + t);
return; // found
}
} while ((t = t.getCause()) != null);
original.printStackTrace(System.out);
throw new RuntimeException("Expected " + clazz + "in " + original);
}
static void printResponse(HttpResponse<?> response) {
out.println("Unexpected response: " + response);
out.println("Headers: " + response.headers());
out.println("Body: " + response.body());
}
// -- Infrastructure
static String serverAuthority(Server server) {
return InetAddress.getLoopbackAddress().getHostName() + ":"
+ server.getPort();
}
@BeforeTest
public void setup() throws Exception {
server = new Server();
httpsURI = URI.create("https://" + serverAuthority(server) + "/foo");
out.println("HTTPS URI: " + httpsURI);
}
@AfterTest
public void teardown() throws Exception {
server.close();
out.printf("%n--- teardown ---%n");
int numClientConnections = variants().length * TIMES;
int serverCount = server.count;
out.printf("Client made %d connections.%n", numClientConnections);
out.printf("Server received %d connections.%n", serverCount);
// This is usually the case, but not always, do not assert. Remains
// as an informative message only.
//if (numClientConnections != serverCount)
// fail(format("[numTests: %d] != [serverCount: %d]",
// numClientConnections, serverCount));
}
/**
* Emulates a server-side, using plain cleartext Sockets, that just reads
* initial client hello and does nothing more.
*/
static class Server extends Thread implements AutoCloseable {
private final ServerSocket ss;
private volatile boolean closed;
volatile int count;
Server() throws IOException {
super("Server");
ss = new ServerSocket();
ss.setReuseAddress(false);
ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
this.start();
}
int getPort() {
return ss.getLocalPort();
}
@Override
public void close() {
if (closed)
return;
closed = true;
try {
ss.close();
} catch (IOException e) {
throw new UncheckedIOException("Unexpected", e);
}
}
@Override
public void run() {
while (!closed) {
try (Socket s = ss.accept()) {
count++;
out.println("Server: accepted new connection");
InputStream is = new BufferedInputStream(s.getInputStream());
out.println("Server: starting to read");
while (is.read() != -1) ;
out.println("Server: closing connection");
s.close(); // close without giving any reply
} catch (IOException e) {
if (!closed)
out.println("UNEXPECTED " + e);
}
}
}
}
}

View File

@ -0,0 +1,46 @@
/*
* 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.
*
* 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.
*/
import java.net.http.HttpClient.Version;
import java.time.Duration;
import org.testng.annotations.Test;
/*
* @test
* @summary Tests connection timeouts during SSL handshake
* @bug 8208391
* @run testng/othervm ConnectTimeoutHandshakeAsync
*/
public class ConnectTimeoutHandshakeAsync
extends AbstractConnectTimeoutHandshake
{
@Test(dataProvider = "variants")
@Override
public void timeoutAsync(Version requestVersion,
String method,
Duration connectTimeout,
Duration requestTimeout) {
super.timeoutAsync(requestVersion, method, connectTimeout, requestTimeout);
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.
*
* 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.
*/
import java.net.http.HttpClient.Version;
import java.time.Duration;
import org.testng.annotations.Test;
/*
* @test
* @summary Tests connection timeouts during SSL handshake
* @bug 8208391
* @run testng/othervm ConnectTimeoutHandshakeSync
*/
public class ConnectTimeoutHandshakeSync
extends AbstractConnectTimeoutHandshake
{
@Test(dataProvider = "variants")
@Override
public void timeoutSync(Version requestVersion,
String method,
Duration connectTimeout,
Duration requestTimeout)
throws Exception
{
super.timeoutSync(requestVersion, method, connectTimeout, requestTimeout);
}
}

View File

@ -0,0 +1,47 @@
/*
* 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.
*
* 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.
*/
import java.net.http.HttpClient.Version;
import java.time.Duration;
import org.testng.annotations.Test;
/*
* @test
* @summary Tests for connection related timeouts
* @bug 8208391
* @run testng/othervm ConnectTimeoutNoProxyAsync
*/
public class ConnectTimeoutNoProxyAsync extends AbstractConnectTimeout {
@Test(dataProvider = "variants")
@Override
public void timeoutNoProxyAsync(Version requestVersion,
String scheme,
String method,
Duration connectTimeout,
Duration requestduration)
{
super.timeoutNoProxyAsync(requestVersion, scheme, method, connectTimeout, requestduration);
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.
*
* 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.
*/
import java.net.http.HttpClient.Version;
import java.time.Duration;
import org.testng.annotations.Test;
/*
* @test
* @summary Tests for connection related timeouts
* @bug 8208391
* @run testng/othervm ConnectTimeoutNoProxySync
*/
public class ConnectTimeoutNoProxySync extends AbstractConnectTimeout {
@Test(dataProvider = "variants")
@Override
public void timeoutNoProxySync(Version requestVersion,
String scheme,
String method,
Duration connectTimeout,
Duration requestTimeout)
throws Exception
{
super.timeoutNoProxySync(requestVersion, scheme, method, connectTimeout, requestTimeout);
}
}

View File

@ -0,0 +1,47 @@
/*
* 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.
*
* 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.
*/
import java.net.http.HttpClient.Version;
import java.time.Duration;
import org.testng.annotations.Test;
/*
* @test
* @summary Tests for connection related timeouts
* @bug 8208391
* @run testng/othervm ConnectTimeoutWithProxyAsync
*/
public class ConnectTimeoutWithProxyAsync extends AbstractConnectTimeout {
@Test(dataProvider = "variants")
@Override
public void timeoutWithProxyAsync(Version requestVersion,
String scheme,
String method,
Duration connectTimeout,
Duration requestTimeout)
{
super.timeoutWithProxyAsync(requestVersion, scheme, method, connectTimeout, requestTimeout);
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.
*
* 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.
*/
import java.net.http.HttpClient.Version;
import java.time.Duration;
import org.testng.annotations.Test;
/*
* @test
* @summary Tests for connection related timeouts
* @bug 8208391
* @run testng/othervm ConnectTimeoutWithProxySync
*/
public class ConnectTimeoutWithProxySync extends AbstractConnectTimeout {
@Test(dataProvider = "variants")
@Override
public void timeoutWithProxySync(Version requestVersion,
String scheme,
String method,
Duration connectTimeout,
Duration requestTimeout)
throws Exception
{
super.timeoutWithProxySync(requestVersion, scheme, method, connectTimeout, requestTimeout);
}
}

View File

@ -50,6 +50,7 @@ import java.net.http.HttpClient.Redirect;
import java.net.http.HttpClient.Version;
import jdk.testlibrary.SimpleSSLContext;
import org.testng.annotations.Test;
import static java.time.Duration.*;
import static org.testng.Assert.*;
/*
@ -74,6 +75,7 @@ public class HttpClientBuilderTest {
// Empty optionals and defaults
assertFalse(client.authenticator().isPresent());
assertFalse(client.cookieHandler().isPresent());
assertFalse(client.connectTimeout().isPresent());
assertFalse(client.executor().isPresent());
assertFalse(client.proxy().isPresent());
assertTrue(client.sslParameters() != null);
@ -88,6 +90,7 @@ public class HttpClientBuilderTest {
HttpClient.Builder builder = HttpClient.newBuilder();
assertThrows(NPE, () -> builder.authenticator(null));
assertThrows(NPE, () -> builder.cookieHandler(null));
assertThrows(NPE, () -> builder.connectTimeout(null));
assertThrows(NPE, () -> builder.executor(null));
assertThrows(NPE, () -> builder.proxy(null));
assertThrows(NPE, () -> builder.sslParameters(null));
@ -128,6 +131,26 @@ public class HttpClientBuilderTest {
assertTrue(builder.build().cookieHandler().get() == c);
}
@Test
public void testConnectTimeout() {
HttpClient.Builder builder = HttpClient.newBuilder();
Duration a = Duration.ofSeconds(5);
builder.connectTimeout(a);
assertTrue(builder.build().connectTimeout().get() == a);
Duration b = Duration.ofMinutes(1);
builder.connectTimeout(b);
assertTrue(builder.build().connectTimeout().get() == b);
assertThrows(NPE, () -> builder.cookieHandler(null));
Duration c = Duration.ofHours(100);
builder.connectTimeout(c);
assertTrue(builder.build().connectTimeout().get() == c);
assertThrows(IAE, () -> builder.connectTimeout(ZERO));
assertThrows(IAE, () -> builder.connectTimeout(ofSeconds(0)));
assertThrows(IAE, () -> builder.connectTimeout(ofSeconds(-1)));
assertThrows(IAE, () -> builder.connectTimeout(ofNanos(-100)));
}
static class TestExecutor implements Executor {
public void execute(Runnable r) { }
}
@ -292,6 +315,7 @@ public class HttpClientBuilderTest {
static class MockHttpClient extends HttpClient {
@Override public Optional<CookieHandler> cookieHandler() { return null; }
@Override public Optional<Duration> connectTimeout() { return null; }
@Override public Redirect followRedirects() { return null; }
@Override public Optional<ProxySelector> proxy() { return null; }
@Override public SSLContext sslContext() { return null; }

View File

@ -164,6 +164,7 @@ public class TimeoutBasic {
throw new RuntimeException("Unexpected response: " + resp.statusCode());
} catch (CompletionException e) {
if (!(e.getCause() instanceof HttpTimeoutException)) {
e.printStackTrace(out);
throw new RuntimeException("Unexpected exception: " + e.getCause());
} else {
out.println("Caught expected timeout: " + e.getCause());

View File

@ -64,6 +64,7 @@ public class JavadocExamples {
HttpClient client = HttpClient.newBuilder()
.version(Version.HTTP_1_1)
.followRedirects(Redirect.NORMAL)
.connectTimeout(Duration.ofSeconds(20))
.proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 80)))
.authenticator(Authenticator.getDefault())
.build();
@ -74,7 +75,7 @@ public class JavadocExamples {
//Asynchronous Example
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://foo.com/"))
.timeout(Duration.ofMinutes(1))
.timeout(Duration.ofMinutes(2))
.header("Content-Type", "application/json")
.POST(BodyPublishers.ofFile(Paths.get("file.json")))
.build();

View File

@ -27,6 +27,7 @@ import java.io.IOException;
import java.net.Authenticator;
import java.net.CookieHandler;
import java.net.ProxySelector;
import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
@ -50,6 +51,11 @@ public class DelegatingHttpClient extends HttpClient {
return client.cookieHandler();
}
@Override
public Optional<Duration> connectTimeout() {
return client.connectTimeout();
}
@Override
public Redirect followRedirects() {
return client.followRedirects();

View File

@ -31,6 +31,7 @@ import java.net.InetSocketAddress;
import java.net.ProxySelector;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
@ -284,7 +285,8 @@ public class ConnectionPoolTest {
// All these throw errors
@Override public HttpPublisher publisher() {return error();}
@Override public CompletableFuture<Void> connectAsync() {return error();}
@Override public CompletableFuture<Void> connectAsync(Exchange<?> e) {return error();}
@Override public CompletableFuture<Void> finishConnect() {return error();}
@Override SocketChannel channel() {return error();}
@Override
FlowTube getConnectionFlow() {return flow;}
@ -296,6 +298,7 @@ public class ConnectionPoolTest {
}
final ConnectionPool pool;
@Override public Optional<CookieHandler> cookieHandler() {return error();}
@Override public Optional<Duration> connectTimeout() {return error();}
@Override public HttpClient.Redirect followRedirects() {return error();}
@Override public Optional<ProxySelector> proxy() {return error();}
@Override public SSLContext sslContext() {return error();}

View File

@ -0,0 +1,390 @@
/*
* 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.
*/
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
/*
* @test
* @bug 8208496
* @summary Test to verify concurrent behavior of TLS.
* @run main/othervm ConcurrentClientAccessTest
*/
public class ConcurrentClientAccessTest {
private static final int THREADS = 50;
public static void main(String[] args) throws Exception {
Security.setProperty("jdk.tls.disabledAlgorithms", "");
for (String tlsProtocol : new String[]{"TLSv1.3", "TLSv1.2",
"TLSv1.1", "TLSv1"}) {
System.out.printf("Protocol: %s%n", tlsProtocol);
CountDownLatch tillServerReady = new CountDownLatch(1);
Server server = new Server(tlsProtocol, tillServerReady);
server.start();
// Wait till server is ready to accept connection.
tillServerReady.await();
CountDownLatch tillClientComplete = new CountDownLatch(THREADS);
ExecutorService executor = null;
try {
executor = newExecutorService();
// Run 50 TLS clients for concurrent access to TLS Port.
for (int count = 1; count <= THREADS; count++) {
Client client = new Client(tlsProtocol, server.port,
tillClientComplete);
executor.execute(client);
// If Client has any Exception indicates problem
if (client.exception != null) {
throw new RuntimeException(client.exception);
}
}
// Wait till all client thread complete execution
tillClientComplete.await();
System.out.println("All client processed successfully.");
} finally {
if (executor != null) {
executor.shutdown();
}
// Fail Safe: Shutdown the server
server.stopServer();
}
// If Sever has any Exception indicates problem
if (server.exception != null) {
throw new RuntimeException(server.exception);
}
System.out.println();
}
}
public static class Server implements Runnable {
private volatile int port = 0;
private final String tlsProtocol;
private final CountDownLatch tillServerReady;
private volatile Exception exception;
private SSLServerSocket sslServerSocket;
public Server(String tlsProtocol, CountDownLatch tillServerReady) {
this.tlsProtocol = tlsProtocol;
this.tillServerReady = tillServerReady;
}
public void start() {
ExecutorService executor = null;
try {
executor = newExecutorService();
executor.execute(this);
} finally {
if (executor != null) {
executor.shutdown();
}
}
}
/*
* Define the server side operation.
*/
void doServerSide() throws Exception {
SSLContext ctx = getSSLContext(tlsProtocol);
SSLServerSocketFactory sslssf = ctx.getServerSocketFactory();
sslServerSocket = (SSLServerSocket) sslssf.createServerSocket(port);
port = sslServerSocket.getLocalPort();
System.out.println("Server listening on port: " + port);
sslServerSocket.setEnabledProtocols(new String[]{tlsProtocol});
// ServerSocket will timeout after waiting for 20 seconds
// before accepting a connection
sslServerSocket.setSoTimeout(20000);
// Signal Client, the server is ready to accept client request.
tillServerReady.countDown();
while (sslServerSocket != null && !sslServerSocket.isClosed()) {
try (SSLSocket sslSocket
= (SSLSocket) sslServerSocket.accept()) {
try (InputStream sslIS = sslSocket.getInputStream();
OutputStream sslOS
= sslSocket.getOutputStream();) {
sslIS.read();
sslOS.write(85);
sslOS.flush();
}
} catch (SocketTimeoutException | SocketException e) {
// Let the server exit
return;
}
}
}
@Override
public void run() {
try {
doServerSide();
} catch (Exception e) {
this.exception = e;
} finally {
// Stop server
stopServer();
}
}
public void stopServer() {
if (sslServerSocket != null && !sslServerSocket.isClosed()) {
System.out.println("Stopping Server.");
try {
sslServerSocket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
/*
* Define the client side of the test.
*/
public static class Client implements Runnable {
private final int serverPort;
private final String tlsProtocol;
private final CountDownLatch tillClientComplete;
private volatile Exception exception;
public Client(String tlsProtocol, int serverPort,
CountDownLatch tillClientComplete) {
this.tlsProtocol = tlsProtocol;
this.serverPort = serverPort;
this.tillClientComplete = tillClientComplete;
}
void doClientSide() throws Exception {
SSLContext ctx = getSSLContext(this.tlsProtocol);
SSLSocketFactory sslsf = ctx.getSocketFactory();
try (SSLSocket sslSocket
= (SSLSocket) sslsf.createSocket("localhost", serverPort)) {
sslSocket.setEnabledProtocols(new String[]{this.tlsProtocol});
try (InputStream sslIS = sslSocket.getInputStream();
OutputStream sslOS = sslSocket.getOutputStream()) {
sslOS.write(86);
sslOS.flush();
sslIS.read();
}
} finally {
tillClientComplete.countDown();
}
}
@Override
public void run() {
try {
doClientSide();
} catch (Exception e) {
// Print the exception for debug purpose.
e.printStackTrace(System.out);
this.exception = e;
}
}
}
// Get the ssl context
protected static SSLContext getSSLContext(String tlsProtocol)
throws Exception {
// Generate certificate from cert string
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// Create a key store
KeyStore ts = KeyStore.getInstance("PKCS12");
KeyStore ks = KeyStore.getInstance("PKCS12");
ts.load(null, null);
ks.load(null, null);
char passphrase[] = "passphrase".toCharArray();
// Import the trusted cert
ts.setCertificateEntry("trusted-cert-"
+ KeyType.rsa_pkcs1_sha256.getKeyType(),
cf.generateCertificate(new ByteArrayInputStream(
KeyType.rsa_pkcs1_sha256.getTrustedCert().getBytes())));
boolean hasKeyMaterials = KeyType.rsa_pkcs1_sha256.getEndCert() != null
&& KeyType.rsa_pkcs1_sha256.getPrivateKey() != null;
if (hasKeyMaterials) {
// Generate the private key.
PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
Base64.getMimeDecoder().decode(
KeyType.rsa_pkcs1_sha256.getPrivateKey()));
KeyFactory kf = KeyFactory.getInstance(
KeyType.rsa_pkcs1_sha256.getKeyType());
PrivateKey priKey = kf.generatePrivate(priKeySpec);
// Generate certificate chain
Certificate keyCert = cf.generateCertificate(
new ByteArrayInputStream(
KeyType.rsa_pkcs1_sha256.getEndCert().getBytes()));
Certificate[] chain = new Certificate[]{keyCert};
// Import the key entry.
ks.setKeyEntry("cert-" + KeyType.rsa_pkcs1_sha256.getKeyType(),
priKey, passphrase, chain);
}
// Create SSL context
TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
tmf.init(ts);
SSLContext context = SSLContext.getInstance(tlsProtocol);
if (hasKeyMaterials) {
KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
kmf.init(ks, passphrase);
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
} else {
context.init(null, tmf.getTrustManagers(), null);
}
return context;
}
private static ExecutorService newExecutorService() {
return Executors.newCachedThreadPool((Runnable r) -> {
Thread t = Executors.defaultThreadFactory()
.newThread(r);
t.setDaemon(true);
return t;
});
}
}
enum KeyType {
rsa_pkcs1_sha256(
"RSA",
/**
* Signature Algorithm: sha256WithRSAEncryption
* Issuer: CN = localhost
* Validity Not Before: Jun 4 15:22:04 2018 GMT
* Not After: May 30 15:22:04 2038 GMT
* Subject: CN = localhost
* Public Key Algorithm: rsaEncryption
*/
"-----BEGIN CERTIFICATE-----\n"
+ "MIIDBjCCAe6gAwIBAgIUc8yTYekR2LuXkkCJYqWlS/pBMKIwDQYJKoZIhvcNAQEL\n"
+ "BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTE4MDYwNDE1MjIwNFoXDTM4MDUz\n"
+ "MDE1MjIwNFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF\n"
+ "AAOCAQ8AMIIBCgKCAQEA2jDPGMogc9dq2w5b+FHqbfaGPokRmyObiU8y/l/dqkM5\n"
+ "9IV+qj8VQUI4NtpdCTWr16812z4AjXrk5HIBrECfQbHPUcm1rme5YVZ0WxV0+Ufy\n"
+ "hDmrGwDLhkxGqc3hOhRrlF2wdXeUfjIzhvS9+S/401++t/jvq+cqFF1BHnzYOu+l\n"
+ "nbi/o95Oqo8MlwiRqg3xy3fNRfqXk7DWy+QT8s+Vc3Pcj1EW6K0iJJ23BVTdv6YT\n"
+ "Ja5IKiWL4XsLht3fWvZwF+PoYfKb+JYflt0rafpxg9xkowe7GnGh2SpV7bJaH/QN\n"
+ "3PTFEKQWgWHjWwjR171GOzSaEgaklvKde6+zNWeYKwIDAQABo1AwTjAdBgNVHQ4E\n"
+ "FgQUqCtGe8/Ky4O6pH7xeTUy9yrv4n0wHwYDVR0jBBgwFoAUqCtGe8/Ky4O6pH7x\n"
+ "eTUy9yrv4n0wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAuqch30im\n"
+ "M09sARarbfK3OExqYK2xoyuUscgTqQNDpNL2gMdXY9e0lTmGVgw9pVYtNZPZRxem\n"
+ "jR5an2XegvG9qVU6vLENDwLCqZgsTb2gvmXngiG8NVcYd81GNqD228mkgBosNJku\n"
+ "6BR+C8zlURzsNEt657eVvIp9ObGomdAbWhpdqihBD180PP18DIBWopyfHfJtT5FA\n"
+ "U2kSPBp+P1EtdceW0zfwv3rF8hwRbnQBzuoYrZfn2PiMYaGUqOgbqUltCMD/Dp9G\n"
+ "xK0nfAXEwIqHWWnijGwAd6YrszMjBUcSGmlehdF+XZK6jHNlw64RB4WTfavr+rY0\n"
+ "dTe6g4o5GYr9nQ==\n"
+ "-----END CERTIFICATE-----\n",
//
// Private key.
//
"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDaMM8YyiBz12rb\n"
+ "Dlv4Uept9oY+iRGbI5uJTzL+X92qQzn0hX6qPxVBQjg22l0JNavXrzXbPgCNeuTk\n"
+ "cgGsQJ9Bsc9RybWuZ7lhVnRbFXT5R/KEOasbAMuGTEapzeE6FGuUXbB1d5R+MjOG\n"
+ "9L35L/jTX763+O+r5yoUXUEefNg676WduL+j3k6qjwyXCJGqDfHLd81F+peTsNbL\n"
+ "5BPyz5Vzc9yPURborSIknbcFVN2/phMlrkgqJYvhewuG3d9a9nAX4+hh8pv4lh+W\n"
+ "3Stp+nGD3GSjB7sacaHZKlXtslof9A3c9MUQpBaBYeNbCNHXvUY7NJoSBqSW8p17\n"
+ "r7M1Z5grAgMBAAECggEAHs/7vw10TcejEHJTrJqs14CT7qresKDzqw1jLycMn6nE\n"
+ "unJLs/EaqE+Yrq5hqxZIQTo+CcsUuuYbAuPStqedleJtW6h3nryJImTaI67BCR8O\n"
+ "8XtPXY3cMAf/hqVLZC9UDey5Ka2Ma9HdEvbnCRSsN/VycnqWJhmMCLouowaQZqoE\n"
+ "VopscUix8GqELv0vEo2CszZfUjtSVbNTlNgwDf5U7eSKXMuFsnSn/LE7AMvHsEyo\n"
+ "HatxogwlM/WjpTnf/WIeJY3VhaK10IsP6OEgUn/p4VtI2DQ/TJdgYrvD5vhjY8ip\n"
+ "XuUPuPILRvJWo8dRXJqa4diXB12q5YhP8iiOp4BgkQKBgQD1GtlOR+JVgOzpQ11h\n"
+ "s5/iJOsczee80pQscbSRJnzSsIaP9WM8CyJgvbPxIQxLUQeYnxM/bxNKkpJtzxRK\n"
+ "pob+v4NoRn8PTpqbOp1obmWJT7uHTaoeavQo7r7uZI4i3eEgHCCQkMzpqzz7UFTY\n"
+ "2Yst7bBTPUivlSVQQBEc8bLpeQKBgQDj47EjpAlh8DmJRTElg58t+XJehXGTqmlx\n"
+ "nYu8DQLSzGbOQ/Z4srakC1mkM0LHCmULIIWk3KhV1GBCeArv7DlZ9A1SkI95bsq9\n"
+ "GBeQpovL0PXKkOOWMJBklP/CTECO4eyA8r6c1d8wytBb6MrJ8bi74DdT+JlFjK5A\n"
+ "zNoeNx6JwwKBgQCehIPABeuSYvRVlDTDqFkh98B6+4wBaatc5xjhuyOFW5dbaVeJ\n"
+ "kKXmLSpAK6B44WnpQhA/uUWfuBWtoPy9nt+1yARjnxwzuSFyfUEqNiPC32coBYmd\n"
+ "bIyGIIopQa1PTXJ4wtgoxw1PnmitHHITYPaLeKrN2te0fuAH+7dVodeU+QKBgAct\n"
+ "VJbaw7Dh7+3yz+lui8TW5lMzwK/13fxGCfCSOFSLO3Gjkk+a0UW5VclmE+RQ333K\n"
+ "OGtIx8RsO9vcC/wiZGwA06qWAu7AHoJ2D8fudtikbBlFFuXUAbgpOSTVYfMeCmTF\n"
+ "QFuQIMdYm9dJLZnOkxLXrOZoHeui0poX2Ya6FawhAoGAAI/QCyDbuvnJzGmjSbvl\n"
+ "5Ndr9lNAansCXaUzXuVLp6dD6PnB8HVCE8tdETZrcXseyTBeltaxAhj+tCybJvDO\n"
+ "sV8UmPR0w9ibExmUIVGX5BpoRlB/KWxEG3ar/wJbUZVZ2oSdIAZvCvdbN956SLDg\n"
+ "Pg5M5wrRqs71s2EiIJd0HrU="
);
private final String keyType;
private final String trustedCert;
private final String endCert;
private final String privateKey;
private KeyType(String keyType, String selfCert, String privateKey) {
this.keyType = keyType;
this.trustedCert = selfCert;
this.endCert = selfCert;
this.privateKey = privateKey;
}
public String getKeyType() {
return keyType;
}
public String getTrustedCert() {
return trustedCert;
}
public String getEndCert() {
return endCert;
}
public String getPrivateKey() {
return privateKey;
}
}

View File

@ -671,7 +671,7 @@ public abstract class PKCS11Test {
"/usr/lib/arm-linux-gnueabi/nss/",
"/usr/lib/arm-linux-gnueabihf/nss/"});
osMap.put("Linux-aarch64-64", new String[]{
"/usr/lib/aarch64-linux-gnu/nss/"});
"/usr/lib/aarch64-linux-gnu/", "/usr/lib/aarch64-linux-gnu/nss/"});
}
private final static char[] hexDigits = "0123456789abcdef".toCharArray();