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
  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 
  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 
  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 }