8149459: StringConcatFactory should be synced up with LambdaMetafactory

Reviewed-by: psandoz, vlivanov, forax
This commit is contained in:
Aleksey Shipilev 2016-02-10 16:36:25 +03:00
parent 32687876fa
commit 7bee07b465
2 changed files with 28 additions and 2 deletions

View File

@ -182,22 +182,30 @@ public final class StringConcatFactory {
private static final ConcurrentMap<Key, MethodHandle> CACHE;
/**
* Dump generated classes to disk, for debugging purposes.
*/
private static final ProxyClassesDumper DUMPER;
static {
// Poke the privileged block once, taking everything we need:
final Object[] values = new Object[3];
final Object[] values = new Object[4];
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
values[0] = System.getProperty("java.lang.invoke.stringConcat");
values[1] = Boolean.getBoolean("java.lang.invoke.stringConcat.cache");
values[2] = Boolean.getBoolean("java.lang.invoke.stringConcat.debug");
values[3] = System.getProperty("java.lang.invoke.stringConcat.dumpClasses");
return null;
});
final String strategy = (String) values[0];
CACHE_ENABLE = (Boolean) values[1];
DEBUG = (Boolean) values[2];
final String dumpPath = (String) values[3];
STRATEGY = (strategy == null) ? DEFAULT_STRATEGY : Strategy.valueOf(strategy);
CACHE = CACHE_ENABLE ? new ConcurrentHashMap<>() : null;
DUMPER = (dumpPath == null) ? null : ProxyClassesDumper.getInstance(dumpPath);
}
private static final class Key {
@ -552,6 +560,12 @@ public final class StringConcatFactory {
Objects.requireNonNull(o, "Cannot accept null constants");
}
if ((lookup.lookupModes() & MethodHandles.Lookup.PRIVATE) == 0) {
throw new StringConcatException(String.format(
"Invalid caller: %s",
lookup.lookupClass().getName()));
}
int cCount = 0;
int oCount = 0;
if (generateRecipe) {
@ -1035,6 +1049,10 @@ public final class StringConcatFactory {
final byte[] classBytes = cw.toByteArray();
final Class<?> innerClass = UNSAFE.defineAnonymousClass(targetClass, classBytes, null);
if (DUMPER != null) {
DUMPER.dumpClass(innerClass.getName(), classBytes);
}
try {
UNSAFE.ensureClassInitialized(innerClass);
return lookup.findStatic(innerClass, NAME_FACTORY, args);

View File

@ -66,7 +66,7 @@ public class StringConcatFactoryInvariants {
private static final char TAG_CONST = '\u0002';
public static void main(String[] args) throws Throwable {
MethodHandles.Lookup lookup = MethodHandles.publicLookup();
MethodHandles.Lookup lookup = MethodHandles.lookup();
String methodName = "foo";
MethodType mt = MethodType.methodType(String.class, String.class, int.class);
String recipe = "" + TAG_ARG + TAG_ARG + TAG_CONST;
@ -236,6 +236,14 @@ public class StringConcatFactoryInvariants {
// Advanced factory: test empty arguments
ok("Ok to pass empty arguments",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtEmpty, recipeEmpty));
// Simple factory: public Lookup is rejected
fail("Passing public Lookup",
() -> StringConcatFactory.makeConcat(MethodHandles.publicLookup(), methodName, mtEmpty));
// Advanced factory: public Lookup is rejected
fail("Passing public Lookup",
() -> StringConcatFactory.makeConcatWithConstants(MethodHandles.publicLookup(), methodName, mtEmpty, recipeEmpty));
}
public static void ok(String msg, Callable runnable) {