1 /*
   2  * Copyright (c) 2017, 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  * @test
  26  * @bug 8046171
  27  * @summary Test access to private constructors between nestmates and nest-host
  28  *          using different flavours of named nested types using method handles
  29  * @run main TestMethodHandles
  30  */
  31 
  32 import java.lang.invoke.*;
  33 import static java.lang.invoke.MethodHandles.*;
  34 import static java.lang.invoke.MethodType.*;
  35 
  36 public class TestMethodHandles {
  37 
  38   static final MethodType NOARG_T = MethodType.methodType(void.class);
  39   static final MethodType INNER_T = MethodType.methodType(void.class, TestMethodHandles.class);
  40 
  41     // All constructors are private to ensure nestmate access checks apply
  42 
  43     // All doConstruct methods are public so they don't involve invoke_special
  44 
  45     private TestMethodHandles() {}
  46 
  47     // The various nestmates
  48 
  49     // Note: No constructor on interfaces so no StaticIface variants
  50 
  51     static interface StaticIface {
  52 
  53         // Methods that will access private constructors of nestmates.
  54         // The arg is a dummy for overloading purposes
  55 
  56         default void doConstruct(TestMethodHandles o) throws Throwable {
  57             MethodHandle mh =
  58               lookup().findConstructor(TestMethodHandles.class, NOARG_T);
  59             TestMethodHandles obj = (TestMethodHandles) mh.invoke();
  60             obj = (TestMethodHandles) mh.invokeExact();
  61         }
  62         default void doConstruct(TestMethodHandles outer, InnerNested o) throws Throwable {
  63             MethodHandle mh =
  64               lookup().findConstructor(InnerNested.class, INNER_T);
  65             InnerNested obj = (InnerNested) mh.invoke(outer);
  66             obj = (InnerNested) mh.invokeExact(outer);
  67         }
  68         default void doConstruct(StaticNested o) throws Throwable {
  69             MethodHandle mh =
  70               lookup().findConstructor(StaticNested.class, NOARG_T);
  71             StaticNested obj = (StaticNested) mh.invoke();
  72             obj = (StaticNested) mh.invokeExact();
  73         }
  74     }
  75 
  76     static class StaticNested {
  77 
  78         private StaticNested() {}
  79 
  80         // Methods that will access private constructors of nestmates.
  81         // The arg is a dummy for overloading purposes
  82 
  83         public void doConstruct(TestMethodHandles o) throws Throwable {
  84             MethodHandle mh =
  85               lookup().findConstructor(TestMethodHandles.class, NOARG_T);
  86             TestMethodHandles obj = (TestMethodHandles) mh.invoke();
  87             obj = (TestMethodHandles) mh.invokeExact();
  88         }
  89         public  void doConstruct(TestMethodHandles outer, InnerNested o) throws Throwable {
  90             MethodHandle mh =
  91               lookup().findConstructor(InnerNested.class, INNER_T);
  92             InnerNested obj = (InnerNested) mh.invoke(outer);
  93             obj = (InnerNested) mh.invokeExact(outer);
  94         }
  95         public void doConstruct(StaticNested o) throws Throwable {
  96             MethodHandle mh =
  97               lookup().findConstructor(StaticNested.class, NOARG_T);
  98             StaticNested obj = (StaticNested) mh.invoke();
  99             obj = (StaticNested) mh.invokeExact();
 100         }
 101     }
 102 
 103     class InnerNested {
 104 
 105         private InnerNested() {}
 106 
 107         // Methods that will access private constructors of nestmates.
 108         // The arg is a dummy for overloading purposes
 109 
 110         public void doConstruct(TestMethodHandles o) throws Throwable {
 111             MethodHandle mh =
 112               lookup().findConstructor(TestMethodHandles.class, NOARG_T);
 113             TestMethodHandles obj = (TestMethodHandles) mh.invoke();
 114             obj = (TestMethodHandles) mh.invokeExact();
 115         }
 116         public  void doConstruct(TestMethodHandles outer, InnerNested o) throws Throwable {
 117             MethodHandle mh =
 118               lookup().findConstructor(InnerNested.class, INNER_T);
 119             InnerNested obj = (InnerNested) mh.invoke(outer);
 120             obj = (InnerNested) mh.invokeExact(outer);
 121         }
 122         public void doConstruct(StaticNested o) throws Throwable {
 123             MethodHandle mh =
 124               lookup().findConstructor(StaticNested.class, NOARG_T);
 125             StaticNested obj = (StaticNested) mh.invoke();
 126             obj = (StaticNested) mh.invokeExact();
 127         }
 128     }
 129 
 130     public static void main(String[] args) throws Throwable {
 131         // These initial constructions test nest-host access
 132         MethodHandle mh =
 133           lookup().findConstructor(TestMethodHandles.class, NOARG_T);
 134         TestMethodHandles o = (TestMethodHandles) mh.invoke();
 135         o = (TestMethodHandles) mh.invokeExact();
 136 
 137         mh = lookup().findConstructor(StaticNested.class, NOARG_T);
 138         StaticNested s = (StaticNested) mh.invoke();
 139         s = (StaticNested) mh.invokeExact();
 140 
 141         mh = lookup().findConstructor(InnerNested.class, INNER_T);
 142         InnerNested i = (InnerNested) mh.invoke(o);
 143         i = (InnerNested) mh.invokeExact(o);
 144 
 145         StaticIface intf = new StaticIface() {};
 146 
 147         s.doConstruct(o);
 148         s.doConstruct(o, i);
 149         s.doConstruct(s);
 150 
 151         i.doConstruct(o);
 152         i.doConstruct(o, i);
 153         i.doConstruct(s);
 154 
 155         intf.doConstruct(o);
 156         intf.doConstruct(o, i);
 157         intf.doConstruct(s);
 158     }
 159 }