Path: blob/master/test/functional/Jsr292/src/com/ibm/j9/jsr292/InterfaceHandleTest.java
6007 views
/*******************************************************************************1* Copyright (c) 2014, 2018 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/21package com.ibm.j9.jsr292;2223import org.testng.annotations.Test;24import org.testng.Assert;25import org.testng.AssertJUnit;26import static org.objectweb.asm.Opcodes.*;2728import java.lang.invoke.MethodHandle;29import java.lang.invoke.MethodHandles;30import java.lang.invoke.MethodType;31import java.lang.reflect.Field;3233import org.objectweb.asm.ClassWriter;34import org.objectweb.asm.MethodVisitor;3536import org.openj9.test.util.VersionCheck;3738/**39* A class to check if a specific method is correctly compiled by JIT40*/41public class InterfaceHandleTest {4243@Test(groups = { "level.extended" })44public void testIfInterfaceHandleIsJitted() throws Throwable {45try {46TestClass_IH clazz = new TestClass_IH();47MethodHandle mh = MethodHandles.lookup().findVirtual(TestInterface.class, "test", MethodType.methodType(void.class));48AssertJUnit.assertTrue(mh.getClass().toString().equals("class java.lang.invoke.InterfaceHandle"));49try {50while (true) {51mh.invokeExact((TestInterface)clazz);52}53} catch (Error t) {54t.printStackTrace();55}56} catch (JittingDetector j) {57AssertJUnit.assertTrue(true);58}59}6061/**62* Class C inherits a public implementation of the method f from class B, which is declared in interface A.63* Because the implementation is public, B.f is a valid implementation of A.f.64*/65@Test(groups = { "level.extended" })66public void test_bindTo_interfaceMethodImplementation_public() throws Throwable {67Helper h = new Helper(ACC_PUBLIC);68MethodHandle mh = MethodHandles.lookup().findVirtual(h.classA, "f", MethodType.methodType(void.class));69mh = mh.bindTo(h.classC.newInstance());70mh.invokeExact();71}7273/**74* Class C inherits a protected implementation of the method f from class B.75* The method is also declared in interface A, which C implements.76* Because the implementation is protected, B.f is an invalid implementation of A.f.77*/78@Test(groups = { "level.extended" })79public void test_bindTo_interfaceMethodImplementation_protected() throws Throwable {80Helper h = new Helper(ACC_PROTECTED);81MethodHandle mh = MethodHandles.lookup().findVirtual(h.classA, "f", MethodType.methodType(void.class));82mh = mh.bindTo(h.classC.newInstance());83try {84mh.invokeExact();85Assert.fail("Successfully invoked protected implementation of an interface method.");86} catch (IllegalAccessError e) { }87}8889/**90* Class C inherits a package private implementation of the method f from class B.91* The method is also declared in interface A, which C implements.92* Because the implementation is package private, B.f is an invalid implementation of A.f.93*/94@Test(groups = { "level.extended" })95public void test_bindTo_interfaceMethodImplementation_package() throws Throwable {96Helper h = new Helper(0);97MethodHandle mh = MethodHandles.lookup().findVirtual(h.classA, "f", MethodType.methodType(void.class));98mh = mh.bindTo(h.classC.newInstance());99try {100mh.invokeExact();101Assert.fail("Successfully invoked package private implementation of an interface method.");102} catch (IllegalAccessError e) { }103}104105/**106* Class C inherits a private implementation of the method f from class B.107* The method is also declared in interface A, which C implements.108* Because the implementation is private, B.f is an invalid implementation of A.f.109*/110@Test(groups = { "level.extended" })111public void test_bindTo_interfaceMethodImplementation_private() throws Throwable {112Helper h = new Helper(ACC_PRIVATE);113MethodHandle mh = MethodHandles.lookup().findVirtual(h.classA, "f", MethodType.methodType(void.class));114mh = mh.bindTo(h.classC.newInstance());115try {116mh.invokeExact();117Assert.fail("Successfully invoked private implementation of an interface method.");118} catch (IllegalAccessError e) {119if (VersionCheck.major() >= 11) {120Assert.fail("IllegalAccessError thrown instead of AbstractMethodError");121}122} catch (AbstractMethodError e) {123if (VersionCheck.major() < 11) {124Assert.fail("AbstractMethodError thrown instead of IllegalAccessError");125}126}127}128129static class Helper {130private static final String CLASS_A = "A";131private static final String CLASS_B = "B";132private static final String CLASS_C = "C";133134Class<?> classA;135Class<?> classB;136Class<?> classC;137138Helper(final int flags) throws ClassNotFoundException {139ClassLoader cl = new ClassLoader() {140public Class<?> findClass(String name) throws ClassNotFoundException {141if (CLASS_A.equals(name)) {142byte[] classFile = getClassA();143return defineClass(CLASS_A, classFile, 0, classFile.length);144} else if (CLASS_B.equals(name)) {145byte[] classFile = getClassB(flags);146return defineClass(CLASS_B, classFile, 0, classFile.length);147} else if (CLASS_C.equals(name)) {148byte[] classFile = getClassC();149return defineClass(CLASS_C, classFile, 0, classFile.length);150}151throw new ClassNotFoundException(name);152}153154/*155* interface A {156* void f();157* }158*/159private byte[] getClassA() {160ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);161MethodVisitor mv;162163cw.visit(49, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, CLASS_A, null, "java/lang/Object", null);164{165mv = cw.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "f", "()V", null, null);166mv.visitEnd();167}168return cw.toByteArray();169}170171/*172* class B {173* [flags] void f() {}174* }175*/176private byte[] getClassB(int flags) {177ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);178MethodVisitor mv;179180cw.visit(49, ACC_PUBLIC | ACC_SUPER, CLASS_B, null, "java/lang/Object", null);181{182mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);183mv.visitCode();184mv.visitVarInsn(ALOAD, 0);185mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);186mv.visitInsn(RETURN);187mv.visitMaxs(0, 0);188mv.visitEnd();189}190{191mv = cw.visitMethod(flags, "f", "()V", null, null);192mv.visitCode();193mv.visitInsn(RETURN);194mv.visitMaxs(0, 0);195mv.visitEnd();196}197return cw.toByteArray();198}199200/*201* class C extends B implements A { }202*/203private byte[] getClassC() {204ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);205MethodVisitor mv;206207cw.visit(49, ACC_PUBLIC | ACC_SUPER, CLASS_C, null, CLASS_B, new String[] {CLASS_A});208{209mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);210mv.visitCode();211mv.visitVarInsn(ALOAD, 0);212mv.visitMethodInsn(INVOKESPECIAL, CLASS_B, "<init>", "()V", false);213mv.visitInsn(RETURN);214mv.visitMaxs(0, 0);215mv.visitEnd();216}217return cw.toByteArray();218}219};220221classA = cl.loadClass(CLASS_A);222classB = cl.loadClass(CLASS_B);223classC = cl.loadClass(CLASS_C);224}225}226}227228class TestClass_IH implements TestInterface {229230static long PC = 0;231232static final Field throwable_walkback;233234static {235Field f;236try {237f = Throwable.class.getDeclaredField("walkback");238f.setAccessible(true);239throwable_walkback = f;240} catch (NoSuchFieldException | SecurityException e) {241throw new RuntimeException();242}243}244245@Test(groups = { "level.extended" })246public void test() throws Throwable {247Throwable t = new Throwable();248Object walkback = throwable_walkback.get(t);249if (walkback instanceof int[]) {250int[] iWalkback = (int[])walkback;251if (PC == 0) {252PC = iWalkback[0];253} else if (PC != iWalkback[0]) {254throw new JittingDetector("detected jitting");255}256} else {257long[] iWalkback = (long[])walkback;258if (PC == 0) {259PC = iWalkback[0];260} else if (PC != iWalkback[0]) {261throw new JittingDetector("detected jitting");262}263}264}265}266267268