1 /*
   2  * Copyright (c) 2015, 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 8087223
  27  * @summary Adding constantTag to keep method call consistent with it.
  28  * @compile -XDignore.symbol.file IntfMethod.java
  29  * @run main/othervm IntfMethod 
  30  * @run main/othervm -Xint IntfMethod 
  31  * @run main/othervm -Xcomp IntfMethod 
  32  */
  33 
  34 
  35 import jdk.internal.org.objectweb.asm.*;
  36 import java.io.FileOutputStream;
  37 import java.lang.reflect.InvocationTargetException;
  38 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  39 
  40 public class IntfMethod {
  41     static byte[] dumpC() {
  42         ClassWriter cw = new ClassWriter(0);
  43         cw.visit(52, ACC_PUBLIC | ACC_SUPER, "C", null, "java/lang/Object", new String[]{"I"});
  44         {
  45             MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
  46             mv.visitCode();
  47             mv.visitVarInsn(ALOAD, 0);
  48             mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
  49             mv.visitInsn(RETURN);
  50             mv.visitMaxs(1, 1);
  51             mv.visitEnd();
  52         }
  53         {
  54             MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "testSpecialIntf", "()V", null, null);
  55             mv.visitCode();
  56             mv.visitVarInsn(ALOAD, 0);
  57             mv.visitMethodInsn(INVOKESPECIAL, "I", "f1", "()V", /*itf=*/false);
  58             mv.visitInsn(RETURN);
  59             mv.visitMaxs(1, 1);
  60             mv.visitEnd();
  61         }
  62         {
  63             MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "testStaticIntf", "()V", null, null);
  64             mv.visitCode();
  65             mv.visitMethodInsn(INVOKESTATIC, "I", "f2", "()V", /*itf=*/false);
  66             mv.visitInsn(RETURN);
  67             mv.visitMaxs(1, 1);
  68             mv.visitEnd();
  69         }
  70         {
  71             MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "testSpecialClass", "()V", null, null);
  72             mv.visitCode();
  73             mv.visitVarInsn(ALOAD, 0);
  74             mv.visitMethodInsn(INVOKESPECIAL, "C", "f1", "()V", /*itf=*/true);
  75             mv.visitInsn(RETURN);
  76             mv.visitMaxs(1, 1);
  77             mv.visitEnd();
  78         }
  79 
  80         {
  81             MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "f2", "()V", null, null);
  82             mv.visitCode();
  83             mv.visitInsn(RETURN);
  84             mv.visitMaxs(0, 1);
  85             mv.visitEnd();
  86         }
  87         {
  88             MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "testStaticClass", "()V", null, null);
  89             mv.visitCode();
  90             mv.visitMethodInsn(INVOKESTATIC, "C", "f2", "()V", /*itf=*/true);
  91             mv.visitInsn(RETURN);
  92             mv.visitMaxs(1, 1);
  93             mv.visitEnd();
  94         }
  95         cw.visitEnd();
  96         return cw.toByteArray();
  97     }
  98 
  99     static byte[] dumpI() {
 100         ClassWriter cw = new ClassWriter(0);
 101         cw.visit(52, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "I", null, "java/lang/Object", null);
 102         {
 103             MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "f1", "()V", null, null);
 104             mv.visitCode();
 105             mv.visitInsn(RETURN);
 106             mv.visitMaxs(0, 1);
 107             mv.visitEnd();
 108         }
 109         {
 110             MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "f2", "()V", null, null);
 111             mv.visitCode();
 112             mv.visitInsn(RETURN);
 113             mv.visitMaxs(0, 1);
 114             mv.visitEnd();
 115         }
 116         cw.visitEnd();
 117         return cw.toByteArray();
 118     }
 119 
 120     static class CL extends ClassLoader {
 121         @Override
 122         protected Class<?> findClass(String name) throws ClassNotFoundException {
 123             byte[] classFile;
 124             switch (name) {
 125                 case "I": classFile = dumpI(); break;
 126                 case "C": classFile = dumpC(); break;
 127                 default:
 128                     throw new ClassNotFoundException(name);
 129             }
 130             return defineClass(name, classFile, 0, classFile.length);
 131         }
 132     }
 133 
 134     public static void main(String[] args) throws Throwable {
 135         Class<?> cls = (new CL()).loadClass("C");
 136         try (FileOutputStream fos = new FileOutputStream("I.class")) { fos.write(dumpI()); }
 137         try (FileOutputStream fos = new FileOutputStream("C.class")) { fos.write(dumpC()); }
 138 
 139         for (String name : new String[] { "testSpecialIntf", "testStaticIntf", "testSpecialClass", "testStaticClass"}) {
 140             System.out.printf("%s: ", name);
 141             try {
 142                 cls.getMethod(name).invoke(cls.newInstance());
 143                 System.out.println("FAILED");
 144                 throw new Exception("Failed to create ICCE");
 145             } catch (Throwable e) {
 146                 if (e instanceof InvocationTargetException &&
 147                     e.getCause() != null && e.getCause() instanceof IncompatibleClassChangeError) {
 148                     System.out.println("PASSED");
 149                     continue;
 150                 } else {
 151                     throw e;
 152                 }
 153             }
 154         }
 155     }
 156 }