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 MethodHandles
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 
TestMethodHandles()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 
doConstruct(TestMethodHandles o)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         }
doConstruct(TestMethodHandles outer, InnerNested o)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         }
doConstruct(StaticNested o)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 
StaticNested()78         private StaticNested() {}
79 
80         // Methods that will access private constructors of nestmates.
81         // The arg is a dummy for overloading purposes
82 
doConstruct(TestMethodHandles o)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         }
doConstruct(TestMethodHandles outer, InnerNested o)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         }
doConstruct(StaticNested o)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 
InnerNested()105         private InnerNested() {}
106 
107         // Methods that will access private constructors of nestmates.
108         // The arg is a dummy for overloading purposes
109 
doConstruct(TestMethodHandles o)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         }
doConstruct(TestMethodHandles outer, InnerNested o)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         }
doConstruct(StaticNested o)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 
main(String[] args)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 }
160