jdk/test/java/lang/invoke/7196190/MHProxyTest.java
changeset 14222 58f55d4dde46
equal deleted inserted replaced
14221:441a3cd5e5e3 14222:58f55d4dde46
       
     1 /*
       
     2  * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 /**
       
    26  * @test
       
    27  * @bug 7196190
       
    28  * @summary Improve method of handling MethodHandles
       
    29  *
       
    30  * @run main/othervm MHProxyTest
       
    31  */
       
    32 
       
    33 import java.lang.invoke.*;
       
    34 import java.security.*;
       
    35 import static java.lang.invoke.MethodHandles.*;
       
    36 import static java.lang.invoke.MethodType.*;
       
    37 
       
    38 public class MHProxyTest {
       
    39     private static final Class<?> C_Unsafe;
       
    40     private static final MethodHandle MH_getUnsafe;
       
    41     static {
       
    42         // Do these before there is a SM installed.
       
    43         C_Unsafe = sun.misc.Unsafe.class;  // EXPECT A WARNING ON THIS LINE
       
    44         Lookup lookup = lookup();
       
    45         MethodHandle gumh = null;
       
    46         try {
       
    47             gumh = lookup.findStatic(C_Unsafe, "getUnsafe", methodType(C_Unsafe));
       
    48         } catch (ReflectiveOperationException ex) {
       
    49             throw new InternalError(ex.toString());
       
    50         }
       
    51         MH_getUnsafe = gumh;
       
    52         // Try some different lookups:
       
    53         try {
       
    54             lookup.in(Object.class).findStatic(C_Unsafe, "getUnsafe", methodType(C_Unsafe));
       
    55         } catch (ReflectiveOperationException ex) {
       
    56             throw new InternalError(ex.toString());
       
    57         }
       
    58         lookup = lookup().in(C_Unsafe);
       
    59         try {
       
    60             lookup.in(C_Unsafe).findStatic(C_Unsafe, "getUnsafe", methodType(C_Unsafe));
       
    61         } catch (ReflectiveOperationException ex) {
       
    62             throw new InternalError(ex.toString());
       
    63         }
       
    64     }
       
    65 
       
    66     public static void main(String[] args) throws Throwable {
       
    67         System.setSecurityManager(new SecurityManager());
       
    68         Lookup lookup = lookup();
       
    69         testBasic(lookup);
       
    70         testDoPriv(lookup);
       
    71         testSetVar();
       
    72         Lookup l2 = lookup.in(Object.class);
       
    73         System.out.println("=== "+l2);
       
    74         testBasic(l2);
       
    75         testDoPriv(l2);
       
    76         Lookup l3 = lookup.in(C_Unsafe);
       
    77         System.out.println("=== "+l3);
       
    78         testBasic(l3);
       
    79         testDoPriv(l3);
       
    80         if (failure != null)
       
    81             throw failure;
       
    82     }
       
    83 
       
    84     private static Throwable failure;
       
    85     private static void fail(Throwable ex) {
       
    86         if (failure == null)
       
    87             failure = ex;
       
    88         StackTraceElement frame = new Exception().getStackTrace()[1];
       
    89         System.out.printf("Failed at %s:%d: %s\n", frame.getFileName(), frame.getLineNumber(), ex);
       
    90     }
       
    91     private static void ok(Throwable ex) {
       
    92         StackTraceElement frame = new Exception().getStackTrace()[1];
       
    93         System.out.printf("OK at %s:%d: %s\n", frame.getFileName(), frame.getLineNumber(), ex);
       
    94     }
       
    95 
       
    96     private static void testBasic(Lookup lookup) throws Throwable {
       
    97         // Verify that we can't get to this guy under the SM:
       
    98         try {
       
    99             MethodHandle badmh = lookup.findStatic(C_Unsafe, "getUnsafe", methodType(C_Unsafe));
       
   100             assert(badmh.type() == methodType(C_Unsafe));
       
   101             badmh = badmh.asType(badmh.type().generic());
       
   102             Object u = C_Unsafe.cast(badmh.invokeExact());
       
   103             assert(C_Unsafe.isInstance(u));
       
   104             fail(new AssertionError("got mh to getUnsafe!"));
       
   105         } catch (SecurityException ex) {
       
   106             ok(ex);
       
   107         }
       
   108         try {
       
   109             Object u = MH_getUnsafe.invokeWithArguments();
       
   110             assert(C_Unsafe.isInstance(u));
       
   111             fail(new AssertionError("got the Unsafe object! (MH invoke)"));
       
   112         } catch (SecurityException ex) {
       
   113             ok(ex);
       
   114         }
       
   115         try {
       
   116             MethodHandle mh = MH_getUnsafe;
       
   117             mh = mh.asType(mh.type().generic());
       
   118             mh = foldArguments(identity(Object.class), mh);
       
   119             mh = filterReturnValue(mh, identity(Object.class));
       
   120             Object u = mh.invokeExact();
       
   121             assert(C_Unsafe.isInstance(u));
       
   122             fail(new AssertionError("got the Unsafe object! (MH invokeWithArguments)"));
       
   123         } catch (SecurityException ex) {
       
   124             ok(ex);
       
   125         }
       
   126     }
       
   127 
       
   128     private static void testDoPriv(Lookup lookup) throws Throwable {
       
   129         PrivilegedAction privAct = MethodHandleProxies.asInterfaceInstance(PrivilegedAction.class, MH_getUnsafe);
       
   130         try {
       
   131             Object u = AccessController.doPrivileged(privAct);
       
   132             assert(C_Unsafe.isInstance(u));
       
   133             fail(new AssertionError("got the Unsafe object! (static doPriv)"));
       
   134         } catch (SecurityException ex) {
       
   135             ok(ex);
       
   136         }
       
   137         MethodHandle MH_doPriv = lookup.findStatic(AccessController.class, "doPrivileged",
       
   138                                                    methodType(Object.class, PrivilegedAction.class));
       
   139         MH_doPriv = MH_doPriv.bindTo(privAct);
       
   140         try {
       
   141             Object u = MH_doPriv.invoke();
       
   142             assert(C_Unsafe.isInstance(u));
       
   143             fail(new AssertionError("got the Unsafe object! (MH + doPriv)"));
       
   144         } catch (SecurityException ex) {
       
   145             ok(ex);
       
   146         }
       
   147         // try one more layer of indirection:
       
   148         Runnable rbl = MethodHandleProxies.asInterfaceInstance(Runnable.class, MH_doPriv);
       
   149         try {
       
   150             rbl.run();
       
   151             fail(new AssertionError("got the Unsafe object! (Runnable + MH + doPriv)"));
       
   152         } catch (SecurityException ex) {
       
   153             ok(ex);
       
   154         }
       
   155     }
       
   156 
       
   157     private static void testSetVar() throws Throwable {
       
   158         {
       
   159             // Test the box pattern:
       
   160             Object[] box = new Object[1];
       
   161             MethodHandle MH_getFoo = identity(Object.class).bindTo("foo");
       
   162             MethodHandle MH_storeToBox = insertArguments(arrayElementSetter(Object[].class), 0, box, 0);
       
   163             MethodHandle mh = filterReturnValue(MH_getFoo, MH_storeToBox);
       
   164             mh.invokeExact();
       
   165             assert(box[0] == "foo");
       
   166         }
       
   167         {
       
   168             Object[] box = new Object[1];
       
   169             MethodHandle MH_storeToBox = insertArguments(arrayElementSetter(Object[].class), 0, box, 0);
       
   170             MethodHandle mh = filterReturnValue(MH_getUnsafe.asType(MH_getUnsafe.type().generic()), MH_storeToBox);
       
   171             try {
       
   172                 mh.invokeExact();
       
   173                 Object u = box[0];
       
   174                 assert(C_Unsafe.isInstance(u));
       
   175                 fail(new AssertionError("got the Unsafe object! (MH + setElement)"));
       
   176             } catch (SecurityException ex) {
       
   177                 ok(ex);
       
   178             }
       
   179         }
       
   180     }
       
   181 }