From c0cda1db4fe74b86faa12136336bdf98c96758d2 Mon Sep 17 00:00:00 2001 From: Ilarion Nakonechnyy Date: Fri, 29 Oct 2021 11:37:45 +0000 Subject: [PATCH] 8273026: Slow LoginContext.login() on multi threading application Reviewed-by: weijun --- .../security/auth/login/LoginContext.java | 39 ++++++++++++++----- test/jdk/javax/security/auth/spi/Loader.java | 19 +++------ .../security/auth/spi/SecondLoginModule.java | 5 --- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/java.base/share/classes/javax/security/auth/login/LoginContext.java b/src/java.base/share/classes/javax/security/auth/login/LoginContext.java index c4dd95b9d3f..9829001133f 100644 --- a/src/java.base/share/classes/javax/security/auth/login/LoginContext.java +++ b/src/java.base/share/classes/javax/security/auth/login/LoginContext.java @@ -40,6 +40,10 @@ import java.util.ServiceLoader; import sun.security.util.PendingException; import sun.security.util.ResourcesMgr; +import java.util.Set; +import java.util.WeakHashMap; +import java.util.stream.*; +import java.util.ServiceLoader.Provider; /** *

The {@code LoginContext} class describes the basic methods used * to authenticate Subjects and provides a way to develop an @@ -222,6 +226,8 @@ public class LoginContext { private static final sun.security.util.Debug debug = sun.security.util.Debug.getInstance("logincontext", "\t[LoginContext]"); + private static final WeakHashMap>> providersCache = + new WeakHashMap<>(); @SuppressWarnings("removal") private void init(String name) throws LoginException { @@ -288,6 +294,7 @@ public class LoginContext { return loader; } }); + } @SuppressWarnings("removal") @@ -691,21 +698,35 @@ public class LoginContext { // locate and instantiate the LoginModule // String name = moduleStack[i].entry.getLoginModuleName(); - @SuppressWarnings("removal") - ServiceLoader sc = AccessController.doPrivileged( - (PrivilegedAction>) - () -> ServiceLoader.load( - LoginModule.class, contextClassLoader)); - for (LoginModule m: sc) { - if (m.getClass().getName().equals(name)) { - moduleStack[i].module = m; + Set> lmProviders; + synchronized(providersCache){ + lmProviders = providersCache.get(contextClassLoader); + if (lmProviders == null){ + if (debug != null){ + debug.println("Build ServiceProviders cache for ClassLoader: " + contextClassLoader.getName()); + } + @SuppressWarnings("removal") + ServiceLoader sc = AccessController.doPrivileged( + (PrivilegedAction>) + () -> java.util.ServiceLoader.load( + LoginModule.class, contextClassLoader)); + lmProviders = sc.stream().collect(Collectors.toSet()); + if (debug != null){ + debug.println("Discovered ServiceProviders for ClassLoader: " + contextClassLoader.getName()); + lmProviders.forEach(System.err::println); + } + providersCache.put(contextClassLoader,lmProviders); + } + } + for (Provider lm: lmProviders){ + if (lm.type().getName().equals(name)){ + moduleStack[i].module = lm.get(); if (debug != null) { debug.println(name + " loaded as a service"); } break; } } - if (moduleStack[i].module == null) { try { @SuppressWarnings("deprecation") diff --git a/test/jdk/javax/security/auth/spi/Loader.java b/test/jdk/javax/security/auth/spi/Loader.java index e2bac97de09..ca071411b8d 100644 --- a/test/jdk/javax/security/auth/spi/Loader.java +++ b/test/jdk/javax/security/auth/spi/Loader.java @@ -26,9 +26,13 @@ import java.io.File; /* * @test - * @bug 8047789 + * @bug 8047789 8273026 * @summary auth.login.LoginContext needs to be updated to work with modules - * @build FirstLoginModule SecondLoginModule + * @comment shows that the SecondLoginModule is still needed even if it's not in the JAAS login config file + * @build FirstLoginModule + * @clean SecondLoginModule + * @run main/othervm/fail Loader + * @build SecondLoginModule * @run main/othervm Loader */ public class Loader { @@ -39,18 +43,7 @@ public class Loader { new File(System.getProperty("test.src"), "sl.conf").toString()); LoginContext lc = new LoginContext("me"); - if (SecondLoginModule.isLoaded) { - throw new Exception(); - } - lc.login(); - // Although only FirstLoginModule is specified in the JAAS login - // config file, LoginContext will first create all LoginModule - // implementations that are registered as services, which include - // SecondLoginModule. - if (!SecondLoginModule.isLoaded) { - throw new Exception(); - } } } diff --git a/test/jdk/javax/security/auth/spi/SecondLoginModule.java b/test/jdk/javax/security/auth/spi/SecondLoginModule.java index c6c85872fa5..a42230a3630 100644 --- a/test/jdk/javax/security/auth/spi/SecondLoginModule.java +++ b/test/jdk/javax/security/auth/spi/SecondLoginModule.java @@ -29,11 +29,6 @@ import java.util.Map; public class SecondLoginModule implements LoginModule { - public static boolean isLoaded; - - public SecondLoginModule() { - isLoaded = true; - } @Override public void initialize(Subject subject, CallbackHandler callbackHandler,