mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8302732: sun/net/www/http/HttpClient/MultiThreadTest.java still failing intermittently
Reviewed-by: dfuchs
This commit is contained in:
parent
db217c9ad6
commit
a2c5a4ac9e
2 changed files with 54 additions and 73 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -36,7 +36,6 @@ import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.locks.Lock;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import jdk.internal.misc.InnocuousThread;
|
import jdk.internal.misc.InnocuousThread;
|
||||||
|
@ -51,7 +50,7 @@ import sun.util.logging.PlatformLogger;
|
||||||
* @author Dave Brown
|
* @author Dave Brown
|
||||||
*/
|
*/
|
||||||
public class KeepAliveCache
|
public class KeepAliveCache
|
||||||
extends HashMap<KeepAliveKey, ClientVector>
|
extends HashMap<KeepAliveKey, KeepAliveCache.ClientVector>
|
||||||
implements Runnable {
|
implements Runnable {
|
||||||
@java.io.Serial
|
@java.io.Serial
|
||||||
private static final long serialVersionUID = -2937172892064557949L;
|
private static final long serialVersionUID = -2937172892064557949L;
|
||||||
|
@ -243,13 +242,16 @@ public class KeepAliveCache
|
||||||
// Remove all outdated HttpClients.
|
// Remove all outdated HttpClients.
|
||||||
cacheLock.lock();
|
cacheLock.lock();
|
||||||
try {
|
try {
|
||||||
|
if (isEmpty()) {
|
||||||
|
// cache not used in the last LIFETIME - exit
|
||||||
|
keepAliveTimer = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
long currentTime = System.currentTimeMillis();
|
long currentTime = System.currentTimeMillis();
|
||||||
List<KeepAliveKey> keysToRemove = new ArrayList<>();
|
List<KeepAliveKey> keysToRemove = new ArrayList<>();
|
||||||
|
|
||||||
for (KeepAliveKey key : keySet()) {
|
for (KeepAliveKey key : keySet()) {
|
||||||
ClientVector v = get(key);
|
ClientVector v = get(key);
|
||||||
v.lock();
|
|
||||||
try {
|
|
||||||
KeepAliveEntry e = v.peekLast();
|
KeepAliveEntry e = v.peekLast();
|
||||||
while (e != null) {
|
while (e != null) {
|
||||||
if ((currentTime - e.idleStartTime) > v.nap) {
|
if ((currentTime - e.idleStartTime) > v.nap) {
|
||||||
|
@ -267,9 +269,6 @@ public class KeepAliveCache
|
||||||
if (v.isEmpty()) {
|
if (v.isEmpty()) {
|
||||||
keysToRemove.add(key);
|
keysToRemove.add(key);
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
v.unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (KeepAliveKey key : keysToRemove) {
|
for (KeepAliveKey key : keysToRemove) {
|
||||||
|
@ -284,7 +283,7 @@ public class KeepAliveCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (!isEmpty());
|
} while (keepAliveTimer == Thread.currentThread());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -301,7 +300,6 @@ public class KeepAliveCache
|
||||||
{
|
{
|
||||||
throw new NotSerializableException();
|
throw new NotSerializableException();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* LIFO order for reusing HttpClients. Most recent entries at the front.
|
/* LIFO order for reusing HttpClients. Most recent entries at the front.
|
||||||
* If > maxConns are in use, discard oldest.
|
* If > maxConns are in use, discard oldest.
|
||||||
|
@ -309,7 +307,6 @@ public class KeepAliveCache
|
||||||
class ClientVector extends ArrayDeque<KeepAliveEntry> {
|
class ClientVector extends ArrayDeque<KeepAliveEntry> {
|
||||||
@java.io.Serial
|
@java.io.Serial
|
||||||
private static final long serialVersionUID = -8680532108106489459L;
|
private static final long serialVersionUID = -8680532108106489459L;
|
||||||
private final ReentrantLock lock = new ReentrantLock();
|
|
||||||
|
|
||||||
// sleep time in milliseconds, before cache clear
|
// sleep time in milliseconds, before cache clear
|
||||||
int nap;
|
int nap;
|
||||||
|
@ -320,8 +317,7 @@ class ClientVector extends ArrayDeque<KeepAliveEntry> {
|
||||||
|
|
||||||
/* return a still valid, idle HttpClient */
|
/* return a still valid, idle HttpClient */
|
||||||
HttpClient get() {
|
HttpClient get() {
|
||||||
lock();
|
assert cacheLock.isHeldByCurrentThread();
|
||||||
try {
|
|
||||||
// check the most recent connection, use if still valid
|
// check the most recent connection, use if still valid
|
||||||
KeepAliveEntry e = peekFirst();
|
KeepAliveEntry e = peekFirst();
|
||||||
if (e == null) {
|
if (e == null) {
|
||||||
|
@ -339,36 +335,21 @@ class ClientVector extends ArrayDeque<KeepAliveEntry> {
|
||||||
}
|
}
|
||||||
return e.hc;
|
return e.hc;
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpClient put(HttpClient h) {
|
HttpClient put(HttpClient h) {
|
||||||
|
assert cacheLock.isHeldByCurrentThread();
|
||||||
HttpClient staleClient = null;
|
HttpClient staleClient = null;
|
||||||
lock();
|
|
||||||
try {
|
|
||||||
assert KeepAliveCache.getMaxConnections() > 0;
|
assert KeepAliveCache.getMaxConnections() > 0;
|
||||||
if (size() >= KeepAliveCache.getMaxConnections()) {
|
if (size() >= KeepAliveCache.getMaxConnections()) {
|
||||||
// remove oldest connection
|
// remove oldest connection
|
||||||
staleClient = removeLast().hc;
|
staleClient = removeLast().hc;
|
||||||
}
|
}
|
||||||
addFirst(new KeepAliveEntry(h, System.currentTimeMillis()));
|
addFirst(new KeepAliveEntry(h, System.currentTimeMillis()));
|
||||||
} finally {
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
// close after releasing the locks
|
// close after releasing the locks
|
||||||
return staleClient;
|
return staleClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
final void lock() {
|
|
||||||
lock.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
final void unlock() {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do not serialize this class!
|
* Do not serialize this class!
|
||||||
*/
|
*/
|
||||||
|
@ -379,11 +360,11 @@ class ClientVector extends ArrayDeque<KeepAliveEntry> {
|
||||||
|
|
||||||
@java.io.Serial
|
@java.io.Serial
|
||||||
private void readObject(ObjectInputStream stream)
|
private void readObject(ObjectInputStream stream)
|
||||||
throws IOException, ClassNotFoundException
|
throws IOException, ClassNotFoundException {
|
||||||
{
|
|
||||||
throw new NotSerializableException();
|
throw new NotSerializableException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class KeepAliveKey {
|
class KeepAliveKey {
|
||||||
private final String protocol;
|
private final String protocol;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -1230,7 +1230,7 @@ public class KeepAliveTest {
|
||||||
System.out.println("ProxyHostUsingSystemProperty:" + System.getProperty("http.proxyHost"));
|
System.out.println("ProxyHostUsingSystemProperty:" + System.getProperty("http.proxyHost"));
|
||||||
System.out.println("http.keepAlive.time.server=" + System.getProperty("http.keepAlive.time.server"));
|
System.out.println("http.keepAlive.time.server=" + System.getProperty("http.keepAlive.time.server"));
|
||||||
System.out.println("http.keepAlive.time.proxy=" + System.getProperty("http.keepAlive.time.proxy"));
|
System.out.println("http.keepAlive.time.proxy=" + System.getProperty("http.keepAlive.time.proxy"));
|
||||||
Class clientVectorClass = Class.forName("sun.net.www.http.ClientVector");
|
Class clientVectorClass = Class.forName("sun.net.www.http.KeepAliveCache$ClientVector");
|
||||||
// System.out.println("clientVectorClass=" + clientVectorClass);
|
// System.out.println("clientVectorClass=" + clientVectorClass);
|
||||||
Field napField = clientVectorClass.getDeclaredField("nap");
|
Field napField = clientVectorClass.getDeclaredField("nap");
|
||||||
napField.setAccessible(true);
|
napField.setAccessible(true);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue