-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cache MethodHandles in LocalCacheFactory and NodeFactory #905
Changes from 1 commit
557aa49
b24b5a5
88a9f13
bf64136
a1aab75
f9cdf54
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,8 @@ | |
import java.lang.invoke.MethodHandle; | ||
import java.lang.invoke.MethodHandles; | ||
import java.lang.invoke.MethodType; | ||
import java.util.Map; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
|
||
import org.checkerframework.checker.nullness.qual.Nullable; | ||
|
||
|
@@ -30,6 +32,7 @@ final class LocalCacheFactory { | |
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); | ||
private static final MethodType FACTORY = MethodType.methodType( | ||
void.class, Caffeine.class, AsyncCacheLoader.class, boolean.class); | ||
private static final Map<String, MethodHandle> CONSTRUCTORS = new ConcurrentHashMap<>(); | ||
|
||
private LocalCacheFactory() {} | ||
|
||
|
@@ -41,7 +44,7 @@ static <K, V> BoundedLocalCache<K, V> newBoundedLocalCache(Caffeine<K, V> builde | |
} | ||
|
||
static String getClassName(Caffeine<?, ?> builder) { | ||
var className = new StringBuilder(LocalCacheFactory.class.getPackageName()).append('.'); | ||
var className = new StringBuilder(); | ||
if (builder.isStrongKeys()) { | ||
className.append('S'); | ||
} else { | ||
|
@@ -80,10 +83,21 @@ static String getClassName(Caffeine<?, ?> builder) { | |
|
||
static <K, V> BoundedLocalCache<K, V> loadFactory(Caffeine<K, V> builder, | ||
@Nullable AsyncCacheLoader<? super K, V> cacheLoader, boolean async, String className) { | ||
var constructor = CONSTRUCTORS.get(className); | ||
if (constructor == null) { | ||
constructor = CONSTRUCTORS.computeIfAbsent(className, LocalCacheFactory::newConstructor); | ||
} | ||
try { | ||
return (BoundedLocalCache<K, V>) constructor.invoke(builder, cacheLoader, async); | ||
} catch (Throwable t) { | ||
throw new IllegalStateException(className, t); | ||
} | ||
} | ||
|
||
static MethodHandle newConstructor(String className) { | ||
try { | ||
Class<?> clazz = Class.forName(className); | ||
MethodHandle handle = LOOKUP.findConstructor(clazz, FACTORY); | ||
return (BoundedLocalCache<K, V>) handle.invoke(builder, cacheLoader, async); | ||
Class<?> clazz = Class.forName(LocalCacheFactory.class.getPackageName() + "." + className); | ||
return LOOKUP.findConstructor(clazz, FACTORY); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change to: This will adapt the return type, so the above call will have correct typoeninformation and invokeExact works. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One additional thing: Since Java 11 I'd use: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/invoke/MethodHandles.Lookup.html#findClass(java.lang.String) So instead of a plain |
||
} catch (RuntimeException | Error e) { | ||
throw e; | ||
} catch (Throwable t) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use invokeExact here after changing the thing below.