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