diff -u new/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthList.java new/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthList.java
--- new/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthList.java 2018-02-23 09:48:44.000000000 +0800
+++ new/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthList.java 2018-02-23 21:57:16.000000000 +0800
@@ -70,7 +70,7 @@
* Puts the authenticator timestamp into the cache in descending order,
* and throw an exception if it's already there.
*/
- public void put(AuthTimeWithHash t, KerberosTime currentTime)
+ public synchronized void put(AuthTimeWithHash t, KerberosTime currentTime)
throws KrbApErrException {
if (entries.isEmpty()) {
@@ -111,34 +111,26 @@
// let us cleanup while we are here
long timeLimit = currentTime.getSeconds() - lifespan;
- long veryOld = timeLimit - (lifespan > 60 ? 60 : lifespan);
- // Only trigger a cleanup when very old entries exist
- // (lifespan + 1 min ago). This ensures a cleanup is done
- // at most every minute.
- if (oldestTime > veryOld) {
+ // Only trigger a cleanup when the earliest entry is
+ // lifespan + 5 sec ago. This ensures a cleanup is done
+ // at most every 5 seconds so that we don't always
+ // addLast(removeLast).
+ if (oldestTime > timeLimit - 5) {
return;
}
// and we remove the *enough* old ones (1 lifetime ago)
- ListIterator<AuthTimeWithHash> it = entries.listIterator(0);
- AuthTimeWithHash temp;
- while (it.hasNext()) {
- // search expired timestamps.
- temp = it.next();
- if (temp.ctime < timeLimit) {
- // It would be nice if ListIterator has a method called stripHere()
- while (!entries.isEmpty()) {
- if (entries.removeLast() == temp) {
- break;
- }
- }
- break;
+ while (!entries.isEmpty()) {
+ AuthTimeWithHash removed = entries.removeLast();
+ if (removed.ctime >= timeLimit) {
+ entries.addLast(removed);
+ oldestTime = removed.ctime;
+ return;
}
}
- AuthTimeWithHash last = entries.peekLast();
- oldestTime = last == null ? Integer.MIN_VALUE : last.ctime;
+ oldestTime = Integer.MIN_VALUE;
}
public boolean isEmpty() {
only in patch2:
unchanged:
--- old/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/MemoryCache.java 2018-02-23 21:57:18.000000000 +0800
+++ new/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/MemoryCache.java 2018-02-23 21:57:18.000000000 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 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
@@ -31,7 +31,9 @@
package sun.security.krb5.internal.rcache;
-import java.util.*;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
import sun.security.krb5.internal.KerberosTime;
import sun.security.krb5.internal.KrbApErrException;
import sun.security.krb5.internal.ReplayCache;
@@ -48,31 +50,17 @@
private static final int lifespan = KerberosTime.getDefaultSkew();
private static final boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
- private final Map<String,AuthList> content = new HashMap<>();
+ private final Map<String,AuthList> content = new ConcurrentHashMap<>();
@Override
public synchronized void checkAndStore(KerberosTime currTime, AuthTimeWithHash time)
throws KrbApErrException {
String key = time.client + "|" + time.server;
- AuthList rc = content.get(key);
+ content.computeIfAbsent(key, k -> new AuthList(lifespan))
+ .put(time, currTime);
if (DEBUG) {
System.out.println("MemoryCache: add " + time + " to " + key);
}
- if (rc == null) {
- rc = new AuthList(lifespan);
- rc.put(time, currTime);
- if (!rc.isEmpty()) {
- content.put(key, rc);
- }
- } else {
- if (DEBUG) {
- System.out.println("MemoryCache: Existing AuthList:\n" + rc);
- }
- rc.put(time, currTime);
- if (rc.isEmpty()) {
- content.remove(key);
- }
- }
}
public String toString() {