8149459: StringConcatFactory should be synced up with LambdaMetafactory
authorshade
Wed, 10 Feb 2016 16:36:25 +0300
changeset 35776 dd5df83fcc0d
parent 35775 00710c1b504a
child 35777 656b9a28f19e
8149459: StringConcatFactory should be synced up with LambdaMetafactory Reviewed-by: psandoz, vlivanov, forax
jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java
jdk/test/java/lang/String/concat/StringConcatFactoryInvariants.java
--- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java	Wed Jan 27 10:35:49 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java	Wed Feb 10 16:36:25 2016 +0300
@@ -182,22 +182,30 @@
 
     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 @@
             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 @@
             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);
--- a/jdk/test/java/lang/String/concat/StringConcatFactoryInvariants.java	Wed Jan 27 10:35:49 2016 +0100
+++ b/jdk/test/java/lang/String/concat/StringConcatFactoryInvariants.java	Wed Feb 10 16:36:25 2016 +0300
@@ -66,7 +66,7 @@
     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 @@
         // 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) {