1 /*
2  * Copyright (c) 2013, 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 8026213
27  * @summary Reflection support for private methods in interfaces
28  * @author  Robert Field
29  * @run main TestPrivateInterfaceMethodReflect
30  */
31 
32 import java.lang.reflect.*;
33 
34 import jdk.internal.org.objectweb.asm.ClassWriter;
35 import jdk.internal.org.objectweb.asm.MethodVisitor;
36 import jdk.internal.org.objectweb.asm.Opcodes;
37 
38 public class TestPrivateInterfaceMethodReflect {
39 
40     static final String INTERFACE_NAME = "PrivateInterfaceMethodReflectTest_Interface";
41     static final String CLASS_NAME = "PrivateInterfaceMethodReflectTest_Class";
42     static final int EXPECTED = 1234;
43 
44     static class TestClassLoader extends ClassLoader implements Opcodes {
45 
46         @Override
findClass(String name)47         public Class findClass(String name) throws ClassNotFoundException {
48             byte[] b;
49             try {
50                 b = loadClassData(name);
51             } catch (Throwable th) {
52                 // th.printStackTrace();
53                 throw new ClassNotFoundException("Loading error", th);
54             }
55             return defineClass(name, b, 0, b.length);
56         }
57 
loadClassData(String name)58         private byte[] loadClassData(String name) throws Exception {
59             ClassWriter cw = new ClassWriter(0);
60             MethodVisitor mv;
61             switch (name) {
62                 case INTERFACE_NAME:
63                     cw.visit(V1_8, ACC_ABSTRACT | ACC_INTERFACE | ACC_PUBLIC, INTERFACE_NAME, null, "java/lang/Object", null);
64                     {
65                         mv = cw.visitMethod(ACC_PRIVATE, "privInstance", "()I", null, null);
66                         mv.visitCode();
67                         mv.visitLdcInsn(EXPECTED);
68                         mv.visitInsn(IRETURN);
69                         mv.visitMaxs(1, 1);
70                         mv.visitEnd();
71                     }
72                     break;
73                 case CLASS_NAME:
74                     cw.visit(52, ACC_SUPER | ACC_PUBLIC, CLASS_NAME, null, "java/lang/Object", new String[]{INTERFACE_NAME});
75                     {
76                         mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
77                         mv.visitCode();
78                         mv.visitVarInsn(ALOAD, 0);
79                         mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
80                         mv.visitInsn(RETURN);
81                         mv.visitMaxs(1, 1);
82                         mv.visitEnd();
83                     }
84                     break;
85                 default:
86                     break;
87             }
88             cw.visitEnd();
89 
90             return cw.toByteArray();
91         }
92     }
93 
main(String[] args)94     public static void main(String[] args) throws Exception {
95         TestClassLoader tcl = new TestClassLoader();
96         Class<?> itf = tcl.loadClass(INTERFACE_NAME);
97         Class<?> k = tcl.loadClass(CLASS_NAME);
98         Object inst = k.newInstance();
99         Method[] meths = itf.getDeclaredMethods();
100         if (meths.length != 1) {
101             throw new Exception("Expected one method in " + INTERFACE_NAME + " instead " + meths.length);
102         }
103 
104         Method m = meths[0];
105         int mod = m.getModifiers();
106         if ((mod & Modifier.PRIVATE) == 0) {
107             throw new Exception("Expected " + m + " to be private");
108         }
109         if ((mod & Modifier.STATIC) != 0) {
110             throw new Exception("Expected " + m + " to be instance method");
111         }
112 
113         m.setAccessible(true);
114         for (int i = 1; i < 200; i++) {
115             if (!m.invoke(inst).equals(EXPECTED)) {
116                 throw new Exception("Expected " + EXPECTED + " from " + m);
117             }
118         }
119 
120         System.out.println("Passed.");
121     }
122 }
123