8344319: SM cleanup in jdk.dynalink module

Reviewed-by: attila
This commit is contained in:
Roger Riggs 2024-11-25 16:46:19 +00:00
parent 15ae8d02ee
commit 593a5898f9
13 changed files with 32 additions and 232 deletions

View File

@ -27,14 +27,10 @@ package jdk.dynalink;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle; import java.lang.invoke.VarHandle;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import jdk.dynalink.internal.AccessControlContextFactory;
import static jdk.dynalink.internal.InternalTypeUtilities.canReferenceDirectly; import static jdk.dynalink.internal.InternalTypeUtilities.canReferenceDirectly;
@ -201,21 +197,14 @@ final class BiClassValue<T> {
} }
} }
@SuppressWarnings("removal")
private static final AccessControlContext GET_CLASS_LOADER_CONTEXT =
AccessControlContextFactory.createAccessControlContext("getClassLoader");
@SuppressWarnings("removal")
private static RetentionDirection getRetentionDirection(Class<?> from, Class<?> to) { private static RetentionDirection getRetentionDirection(Class<?> from, Class<?> to) {
return AccessController.doPrivileged((PrivilegedAction<RetentionDirection>) () -> { final ClassLoader cl1 = from.getClassLoader();
final ClassLoader cl1 = from.getClassLoader(); final ClassLoader cl2 = to.getClassLoader();
final ClassLoader cl2 = to.getClassLoader(); if (canReferenceDirectly(cl1, cl2)) {
if (canReferenceDirectly(cl1, cl2)) { return RetentionDirection.FORWARD;
return RetentionDirection.FORWARD; } else if (canReferenceDirectly(cl2, cl1)) {
} else if (canReferenceDirectly(cl2, cl1)) { return RetentionDirection.REVERSE;
return RetentionDirection.REVERSE; }
} return RetentionDirection.NEITHER;
return RetentionDirection.NEITHER;
}, GET_CLASS_LOADER_CONTEXT);
} }
} }

View File

@ -63,9 +63,6 @@ package jdk.dynalink;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType; import java.lang.invoke.MethodType;
import java.lang.invoke.MutableCallSite; import java.lang.invoke.MutableCallSite;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -79,7 +76,6 @@ import java.util.ServiceLoader;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier; import java.util.function.Supplier;
import jdk.dynalink.beans.BeansLinker; import jdk.dynalink.beans.BeansLinker;
import jdk.dynalink.internal.AccessControlContextFactory;
import jdk.dynalink.linker.GuardedInvocation; import jdk.dynalink.linker.GuardedInvocation;
import jdk.dynalink.linker.GuardedInvocationTransformer; import jdk.dynalink.linker.GuardedInvocationTransformer;
import jdk.dynalink.linker.GuardingDynamicLinker; import jdk.dynalink.linker.GuardingDynamicLinker;
@ -108,10 +104,6 @@ import jdk.dynalink.linker.support.TypeUtilities;
* @since 9 * @since 9
*/ */
public final class DynamicLinkerFactory { public final class DynamicLinkerFactory {
@SuppressWarnings("removal")
private static final AccessControlContext GET_CLASS_LOADER_CONTEXT =
AccessControlContextFactory.createAccessControlContext("getClassLoader");
/** /**
* Default value for {@link #setUnstableRelinkThreshold(int) unstable relink * Default value for {@link #setUnstableRelinkThreshold(int) unstable relink
* threshold}. * threshold}.
@ -430,17 +422,14 @@ public final class DynamicLinkerFactory {
private List<GuardingDynamicLinker> discoverAutoLoadLinkers() { private List<GuardingDynamicLinker> discoverAutoLoadLinkers() {
autoLoadingErrors = new LinkedList<>(); autoLoadingErrors = new LinkedList<>();
final ClassLoader effectiveClassLoader = classLoaderExplicitlySet ? classLoader : getThreadContextClassLoader(); final ClassLoader effectiveClassLoader =
classLoaderExplicitlySet ? classLoader : Thread.currentThread().getContextClassLoader();
final List<GuardingDynamicLinker> discovered = new LinkedList<>(); final List<GuardingDynamicLinker> discovered = new LinkedList<>();
try { try {
@SuppressWarnings("removal")
final ServiceLoader<GuardingDynamicLinkerExporter> linkerLoader = final ServiceLoader<GuardingDynamicLinkerExporter> linkerLoader =
AccessController.doPrivileged((PrivilegedAction<ServiceLoader<GuardingDynamicLinkerExporter>>)()-> { (effectiveClassLoader == null)
if (effectiveClassLoader == null) { ? ServiceLoader.loadInstalled(GuardingDynamicLinkerExporter.class)
return ServiceLoader.loadInstalled(GuardingDynamicLinkerExporter.class); : ServiceLoader.load(GuardingDynamicLinkerExporter.class, effectiveClassLoader);
}
return ServiceLoader.load(GuardingDynamicLinkerExporter.class, effectiveClassLoader);
});
for(final Iterator<GuardingDynamicLinkerExporter> it = linkerLoader.iterator(); it.hasNext();) { for(final Iterator<GuardingDynamicLinkerExporter> it = linkerLoader.iterator(); it.hasNext();) {
try { try {
@ -470,13 +459,6 @@ public final class DynamicLinkerFactory {
return discovered; return discovered;
} }
@SuppressWarnings("removal")
private static ClassLoader getThreadContextClassLoader() {
return AccessController.doPrivileged(
(PrivilegedAction<ClassLoader>) () -> Thread.currentThread().getContextClassLoader(),
GET_CLASS_LOADER_CONTEXT);
}
private static void addClasses(final Set<Class<? extends GuardingDynamicLinker>> knownLinkerClasses, private static void addClasses(final Set<Class<? extends GuardingDynamicLinker>> knownLinkerClasses,
final List<? extends GuardingDynamicLinker> linkers) { final List<? extends GuardingDynamicLinker> linkers) {
for(final GuardingDynamicLinker linker: linkers) { for(final GuardingDynamicLinker linker: linkers) {

View File

@ -45,8 +45,6 @@ public class SecureLookupSupplier {
*/ */
public static final String GET_LOOKUP_PERMISSION_NAME = "dynalink.getLookup"; public static final String GET_LOOKUP_PERMISSION_NAME = "dynalink.getLookup";
private static final RuntimePermission GET_LOOKUP_PERMISSION = new RuntimePermission(SecureLookupSupplier.GET_LOOKUP_PERMISSION_NAME);
private final MethodHandles.Lookup lookup; private final MethodHandles.Lookup lookup;
/** /**
@ -63,11 +61,6 @@ public class SecureLookupSupplier {
* @return the lookup secured by this {@code SecureLookupSupplier}. * @return the lookup secured by this {@code SecureLookupSupplier}.
*/ */
public final Lookup getLookup() { public final Lookup getLookup() {
@SuppressWarnings("removal")
final SecurityManager sm = System.getSecurityManager();
if (sm != null && lookup != MethodHandles.publicLookup()) {
sm.checkPermission(GET_LOOKUP_PERMISSION);
}
return lookup; return lookup;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2010, 2024, 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
@ -63,8 +63,6 @@ package jdk.dynalink.beans;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.RecordComponent; import java.lang.reflect.RecordComponent;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -86,20 +84,12 @@ class BeanIntrospector extends FacetIntrospector {
@Override Collection<Method> getRecordComponentGetters() { @Override Collection<Method> getRecordComponentGetters() {
if (clazz.isRecord()) { if (clazz.isRecord()) {
try { final RecordComponent[] rcs = clazz.getRecordComponents();
// Need to use doPrivileged as getRecordComponents is rather strict. return Arrays.stream(rcs)
@SuppressWarnings("removal") .map(RecordComponent::getAccessor)
final RecordComponent[] rcs = AccessController.doPrivileged( .map(membersLookup::getAccessibleMethod)
(PrivilegedAction<RecordComponent[]>) clazz::getRecordComponents); .filter(Objects::nonNull) // no accessible counterpart
return Arrays.stream(rcs) .toList();
.map(RecordComponent::getAccessor)
.map(membersLookup::getAccessibleMethod)
.filter(Objects::nonNull) // no accessible counterpart
.toList();
} catch (SecurityException e) {
// We couldn't execute getRecordComponents.
return List.of();
}
} else { } else {
return List.of(); return List.of();
} }

View File

@ -67,12 +67,8 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Executable; import java.lang.reflect.Executable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import jdk.dynalink.CallSiteDescriptor; import jdk.dynalink.CallSiteDescriptor;
import jdk.dynalink.SecureLookupSupplier;
import jdk.dynalink.internal.AccessControlContextFactory;
import jdk.dynalink.linker.support.Lookup; import jdk.dynalink.linker.support.Lookup;
/** /**
@ -82,10 +78,6 @@ import jdk.dynalink.linker.support.Lookup;
* every request. * every request.
*/ */
class CallerSensitiveDynamicMethod extends SingleDynamicMethod { class CallerSensitiveDynamicMethod extends SingleDynamicMethod {
@SuppressWarnings("removal")
private static final AccessControlContext GET_LOOKUP_CONTEXT =
AccessControlContextFactory.createAccessControlContext(
SecureLookupSupplier.GET_LOOKUP_PERMISSION_NAME);
private final Executable target; private final Executable target;
private final MethodType type; private final MethodType type;
@ -127,10 +119,7 @@ class CallerSensitiveDynamicMethod extends SingleDynamicMethod {
@Override @Override
MethodHandle getTarget(final CallSiteDescriptor desc) { MethodHandle getTarget(final CallSiteDescriptor desc) {
@SuppressWarnings("removal") final MethodHandles.Lookup lookup = desc.getLookup();
final MethodHandles.Lookup lookup = AccessController.doPrivileged(
(PrivilegedAction<MethodHandles.Lookup>)desc::getLookup,
GET_LOOKUP_CONTEXT);
if(target instanceof Method) { if(target instanceof Method) {
final MethodHandle mh = unreflect(lookup, (Method)target); final MethodHandle mh = unreflect(lookup, (Method)target);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2010, 2024, 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
@ -61,25 +61,17 @@
package jdk.dynalink.beans; package jdk.dynalink.beans;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import jdk.dynalink.internal.AccessControlContextFactory;
/** /**
* A utility class to check whether a given class is in a package with restricted access e.g. "sun.*" etc. * A utility class to check whether a given class is in a package with restricted access e.g. "sun.*" etc.
*/ */
class CheckRestrictedPackage { class CheckRestrictedPackage {
@SuppressWarnings("removal")
private static final AccessControlContext NO_PERMISSIONS_CONTEXT =
AccessControlContextFactory.createAccessControlContext();
/** /**
* Returns true if the class is either not public, or it resides in a package with restricted access. * Returns true if the class is either not public, or it resides in a package with restricted access.
* @param clazz the class to test * @param clazz the class to test
* @return true if the class is either not public, or it resides in a package with restricted access. * @return true if the class is either not public, or it resides in a package with restricted access.
*/ */
@SuppressWarnings("removal")
static boolean isRestrictedClass(final Class<?> clazz) { static boolean isRestrictedClass(final Class<?> clazz) {
if(!Modifier.isPublic(clazz.getModifiers())) { if(!Modifier.isPublic(clazz.getModifiers())) {
// Non-public classes are always restricted // Non-public classes are always restricted
@ -97,21 +89,6 @@ class CheckRestrictedPackage {
// Classes in unexported packages of modules are always restricted // Classes in unexported packages of modules are always restricted
return true; return true;
} }
final SecurityManager sm = System.getSecurityManager();
if(sm == null) {
// No further restrictions if we don't have a security manager
return false;
}
// Do a package access check from within an access control context with no permissions
try {
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
sm.checkPackageAccess(pkgName);
return null;
}, NO_PERMISSIONS_CONTEXT);
} catch(final SecurityException e) {
return true;
}
return false; return false;
} }
} }

View File

@ -61,13 +61,10 @@
package jdk.dynalink.beans; package jdk.dynalink.beans;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays; import java.util.Arrays;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import jdk.dynalink.internal.AccessControlContextFactory;
import jdk.dynalink.internal.InternalTypeUtilities; import jdk.dynalink.internal.InternalTypeUtilities;
import jdk.dynalink.linker.LinkerServices; import jdk.dynalink.linker.LinkerServices;
import jdk.dynalink.linker.support.TypeUtilities; import jdk.dynalink.linker.support.TypeUtilities;
@ -78,10 +75,6 @@ import jdk.dynalink.linker.support.TypeUtilities;
* JLS. * JLS.
*/ */
final class ClassString { final class ClassString {
@SuppressWarnings("removal")
private static final AccessControlContext GET_CLASS_LOADER_CONTEXT =
AccessControlContextFactory.createAccessControlContext("getClassLoader");
/** /**
* An anonymous inner class used solely to represent the "type" of null values for method applicability checking. * An anonymous inner class used solely to represent the "type" of null values for method applicability checking.
*/ */
@ -128,16 +121,13 @@ final class ClassString {
return "ClassString[" + Arrays.toString(classes) + "]"; return "ClassString[" + Arrays.toString(classes) + "]";
} }
@SuppressWarnings("removal")
boolean isVisibleFrom(final ClassLoader classLoader) { boolean isVisibleFrom(final ClassLoader classLoader) {
return AccessController.doPrivileged((PrivilegedAction<Boolean>) () -> { for(final Class<?> clazz: classes) {
for(final Class<?> clazz: classes) { if(!InternalTypeUtilities.canReferenceDirectly(classLoader, clazz.getClassLoader())) {
if(!InternalTypeUtilities.canReferenceDirectly(classLoader, clazz.getClassLoader())) { return false;
return false;
}
} }
return true; }
}, GET_CLASS_LOADER_CONTEXT); return true;
} }
List<MethodHandle> getMaximallySpecifics(final List<MethodHandle> methods, final LinkerServices linkerServices, final boolean varArg) { List<MethodHandle> getMaximallySpecifics(final List<MethodHandle> methods, final LinkerServices linkerServices, final boolean varArg) {

View File

@ -62,9 +62,6 @@ package jdk.dynalink.beans;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType; import java.lang.invoke.MethodType;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.Collator; import java.text.Collator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.IdentityHashMap; import java.util.IdentityHashMap;
@ -73,9 +70,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import jdk.dynalink.CallSiteDescriptor; import jdk.dynalink.CallSiteDescriptor;
import jdk.dynalink.SecureLookupSupplier;
import jdk.dynalink.beans.ApplicableOverloadedMethods.ApplicabilityTest; import jdk.dynalink.beans.ApplicableOverloadedMethods.ApplicabilityTest;
import jdk.dynalink.internal.AccessControlContextFactory;
import jdk.dynalink.internal.InternalTypeUtilities; import jdk.dynalink.internal.InternalTypeUtilities;
import jdk.dynalink.linker.LinkerServices; import jdk.dynalink.linker.LinkerServices;
@ -194,16 +189,8 @@ class OverloadedDynamicMethod extends DynamicMethod {
} }
} }
@SuppressWarnings("removal")
private static final AccessControlContext GET_CALL_SITE_CLASS_LOADER_CONTEXT =
AccessControlContextFactory.createAccessControlContext(
"getClassLoader", SecureLookupSupplier.GET_LOOKUP_PERMISSION_NAME);
@SuppressWarnings("removal")
private static ClassLoader getCallSiteClassLoader(final CallSiteDescriptor callSiteDescriptor) { private static ClassLoader getCallSiteClassLoader(final CallSiteDescriptor callSiteDescriptor) {
return AccessController.doPrivileged( return callSiteDescriptor.getLookup().lookupClass().getClassLoader();
(PrivilegedAction<ClassLoader>) () -> callSiteDescriptor.getLookup().lookupClass().getClassLoader(),
GET_CALL_SITE_CLASS_LOADER_CONTEXT);
} }
@Override @Override

View File

@ -1,80 +0,0 @@
/*
* Copyright (c) 2015, 2021, 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.dynalink.internal;
import java.security.AccessControlContext;
import java.security.Permission;
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.util.stream.Stream;
/**
* Utility class for creating permission-restricting {@link AccessControlContext}s.
*/
public final class AccessControlContextFactory {
private AccessControlContextFactory () {
}
/**
* Creates an access control context with no permissions.
* @return an access control context with no permissions.
*/
@SuppressWarnings("removal")
public static AccessControlContext createAccessControlContext() {
return createAccessControlContext(new Permission[0]);
}
/**
* Creates an access control context limited to only the specified permissions.
* @param permissions the permissions for the newly created access control context.
* @return a new access control context limited to only the specified permissions.
*/
@SuppressWarnings("removal")
public static AccessControlContext createAccessControlContext(final Permission... permissions) {
final Permissions perms = new Permissions();
for(final Permission permission: permissions) {
perms.add(permission);
}
return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, perms) });
}
/**
* Creates an access control context limited to only the {@link RuntimePermission}s
* of the given names.
* @param runtimePermissionNames the names of runtime permissions for the
* newly created access control context.
* @return a new access control context limited to only the runtime
* permissions with the specified names.
*/
@SuppressWarnings("removal")
public static AccessControlContext createAccessControlContext(final String... runtimePermissionNames) {
return createAccessControlContext(makeRuntimePermissions(runtimePermissionNames));
}
private static Permission[] makeRuntimePermissions(final String... runtimePermissionNames) {
return Stream.of(runtimePermissionNames).map(RuntimePermission::new).toArray(Permission[]::new);
}
}

View File

@ -63,9 +63,6 @@ public class InternalTypeUtilities {
* @param referredLoader the referred class loader * @param referredLoader the referred class loader
* @return true if it is safe to strongly reference the class from referred * @return true if it is safe to strongly reference the class from referred
* in referred. * in referred.
* @throws SecurityException if the caller does not have the
* {@code RuntimePermission("getClassLoader")} permission and the method
* needs to traverse the parent class loader chain.
*/ */
public static boolean canReferenceDirectly(final ClassLoader referrerLoader, final ClassLoader referredLoader) { public static boolean canReferenceDirectly(final ClassLoader referrerLoader, final ClassLoader referredLoader) {
if(referredLoader == null) { if(referredLoader == null) {

View File

@ -52,16 +52,9 @@ public abstract class GuardingDynamicLinkerExporter implements Supplier<List<Gua
*/ */
public static final String AUTOLOAD_PERMISSION_NAME = "dynalink.exportLinkersAutomatically"; public static final String AUTOLOAD_PERMISSION_NAME = "dynalink.exportLinkersAutomatically";
private static final Permission AUTOLOAD_PERMISSION = new RuntimePermission(AUTOLOAD_PERMISSION_NAME);
/** /**
* Creates a new linker exporter. * Creates a new linker exporter.
*/ */
protected GuardingDynamicLinkerExporter() { protected GuardingDynamicLinkerExporter() {
@SuppressWarnings("removal")
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(AUTOLOAD_PERMISSION);
}
} }
} }

View File

@ -115,11 +115,7 @@ public interface GuardingTypeConverterFactory {
* it will return the public lookup. A typical case where the lookup might * it will return the public lookup. A typical case where the lookup might
* be needed is when the converter creates a Java adapter class on the fly * be needed is when the converter creates a Java adapter class on the fly
* (e.g. to convert some object from the dynamic language into a Java * (e.g. to convert some object from the dynamic language into a Java
* interface for interoperability). Invoking the {@link Supplier#get()} * interface for interoperability).
* method on the passed supplier will be subject to the same security checks
* as {@link SecureLookupSupplier#getLookup()}. An implementation should avoid
* retrieving the lookup if it is not needed so as to avoid the expense of
* {@code AccessController.doPrivileged} call.
* @return a guarded invocation that can take an object (if it passes guard) * @return a guarded invocation that can take an object (if it passes guard)
* and return another object that is its representation coerced into the * and return another object that is its representation coerced into the
* target type. In case the factory is certain it is unable to handle a * target type. In case the factory is certain it is unable to handle a

View File

@ -215,10 +215,7 @@ public interface LinkerServices {
* operation to the context of some caller class, consider performing it * operation to the context of some caller class, consider performing it
* within an invocation of this method and passing a full-strength lookup * within an invocation of this method and passing a full-strength lookup
* for that class, as it will associate that lookup with the current thread * for that class, as it will associate that lookup with the current thread
* for the duration of the operation. Note that since you are passing a * for the duration of the operation.
* {@link SecureLookupSupplier}, any invoked type converter factories will
* still need to hold the necessary runtime permission to be able to get the
* lookup should they need it.
* @param <T> the type of the return value provided by the passed-in supplier. * @param <T> the type of the return value provided by the passed-in supplier.
* @param operation the operation to execute in context of the specified lookup. * @param operation the operation to execute in context of the specified lookup.
* @param lookupSupplier secure supplier of the lookup * @param lookupSupplier secure supplier of the lookup