Path: blob/master/test/functional/Jsr292/src/com/ibm/j9/jsr292/VirtualHandleTest.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.AssertJUnit;25import java.lang.invoke.MethodHandle;26import java.lang.invoke.MethodHandles;27import java.lang.invoke.MethodType;28import java.lang.reflect.*;2930import org.objectweb.asm.*;31import static org.objectweb.asm.Opcodes.*;3233/**34* A class to check if a specific method is correctly compiled by JIT35*/36public class VirtualHandleTest {3738@Test(groups = { "level.extended" })39public void testIfVirtualHandleTestIsJitted() throws Throwable {40try {41TestClass_VH clazz = new TestClass_VH();42MethodHandle mh = MethodHandles.lookup().findVirtual(TestClass_VH.class, "test", MethodType.methodType(void.class));43AssertJUnit.assertTrue(mh.getClass().toString().equals("class java.lang.invoke.VirtualHandle"));44try {45while (true) {46mh.invokeExact((TestClass_VH)clazz);47}48} catch (Error t) {49t.printStackTrace();50}51} catch (JittingDetector j) {52AssertJUnit.assertTrue(true);53}54}5556/**57* Class A declares a public method f. Class B extends A and overrides f with a protected implementation.58* Class C extends B. A virtual invocation of f on C finds the protected method B.f.59* According to the reference implementation, this B.f is a valid virtual resolution.60*/61@Test(groups = { "level.extended" })62public void test_bindTo_narrowedMethodImplementation_protected() throws Throwable {63Helper h = new Helper(ACC_PROTECTED);64MethodHandle mh = MethodHandles.lookup().findVirtual(h.classA, "f", MethodType.methodType(void.class));65mh = mh.bindTo(h.classC.newInstance());66mh.invokeExact();67}6869/**70* Class A declares a public method f. Class B extends A and overrides f with a package private implementation.71* Class C extends B. A virtual invocation of f on C finds the package private method B.f.72* According to the reference implementation, this B.f is a valid virtual resolution.73*/74@Test(groups = { "level.extended" })75public void test_bindTo_narrowedMethodImplementation_package() throws Throwable {76Helper h = new Helper(0);77MethodHandle mh = MethodHandles.lookup().findVirtual(h.classA, "f", MethodType.methodType(void.class));78mh = mh.bindTo(h.classC.newInstance());79mh.invokeExact();80}8182/**83* Class A declares a public method f. Class B extends A and overrides f with a private implementation.84* Class C extends B. A virtual invocation of f on C finds the private method B.f.85* According to the reference implementation, this B.f is a valid virtual resolution.86*/87@Test(groups = { "level.extended" })88public void test_bindTo_narrowedMethodImplementation_private() throws Throwable {89Helper h = new Helper(ACC_PRIVATE);90MethodHandle mh = MethodHandles.lookup().findVirtual(h.classA, "f", MethodType.methodType(void.class));91mh = mh.bindTo(h.classC.newInstance());92mh.invokeExact();93}9495static class Helper {96private static final String CLASS_A = "A";97private static final String CLASS_B = "B";98private static final String CLASS_C = "C";99100Class<?> classA;101Class<?> classB;102Class<?> classC;103104Helper(final int flags) throws ClassNotFoundException {105ClassLoader cl = new ClassLoader() {106public Class<?> findClass(String name) throws ClassNotFoundException {107if (CLASS_A.equals(name)) {108byte[] classFile = getClassA();109return defineClass(CLASS_A, classFile, 0, classFile.length);110} else if (CLASS_B.equals(name)) {111byte[] classFile = getClassB(flags);112return defineClass(CLASS_B, classFile, 0, classFile.length);113} else if (CLASS_C.equals(name)) {114byte[] classFile = getClassC();115return defineClass(CLASS_C, classFile, 0, classFile.length);116}117throw new ClassNotFoundException(name);118}119120/*121* class A {122* public void f() {}123* }124*/125private byte[] getClassA() {126ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);127MethodVisitor mv;128129cw.visit(49, ACC_PUBLIC | ACC_SUPER, CLASS_A, null, "java/lang/Object", null);130{131mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);132mv.visitCode();133mv.visitVarInsn(ALOAD, 0);134mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);135mv.visitInsn(RETURN);136mv.visitMaxs(0, 0);137mv.visitEnd();138}139{140mv = cw.visitMethod(ACC_PUBLIC, "f", "()V", null, null);141mv.visitCode();142mv.visitInsn(RETURN);143mv.visitMaxs(0, 0);144mv.visitEnd();145}146return cw.toByteArray();147}148149/*150* class B extends A {151* [flags] void f() {}152* }153*/154private byte[] getClassB(int flags) {155ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);156MethodVisitor mv;157158cw.visit(49, ACC_PUBLIC | ACC_SUPER, CLASS_B, null, CLASS_A, null);159{160mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);161mv.visitCode();162mv.visitVarInsn(ALOAD, 0);163mv.visitMethodInsn(INVOKESPECIAL, CLASS_A, "<init>", "()V", false);164mv.visitInsn(RETURN);165mv.visitMaxs(0, 0);166mv.visitEnd();167}168{169mv = cw.visitMethod(flags, "f", "()V", null, null);170mv.visitCode();171mv.visitInsn(RETURN);172mv.visitMaxs(0, 0);173mv.visitEnd();174}175return cw.toByteArray();176}177178/*179* class C extends B { }180*/181private byte[] getClassC() {182ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);183MethodVisitor mv;184185cw.visit(49, ACC_PUBLIC | ACC_SUPER, CLASS_C, null, CLASS_B, null);186{187mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);188mv.visitCode();189mv.visitVarInsn(ALOAD, 0);190mv.visitMethodInsn(INVOKESPECIAL, CLASS_B, "<init>", "()V", false);191mv.visitInsn(RETURN);192mv.visitMaxs(0, 0);193mv.visitEnd();194}195return cw.toByteArray();196}197};198199classA = cl.loadClass(CLASS_A);200classB = cl.loadClass(CLASS_B);201classC = cl.loadClass(CLASS_C);202}203}204}205206class TestClass_VH {207208static long PC = 0;209210static final Field throwable_walkback;211212static {213Field f;214try {215f = Throwable.class.getDeclaredField("walkback");216f.setAccessible(true);217throwable_walkback = f;218} catch (NoSuchFieldException | SecurityException e) {219throw new RuntimeException();220}221}222223public void test() throws Throwable {224Throwable t = new Throwable();225Object walkback = throwable_walkback.get(t);226if (walkback instanceof int[]) {227int[] iWalkback = (int[])walkback;228if (PC == 0) {229PC = iWalkback[0];230} else if (PC != iWalkback[0]) {231throw new JittingDetector("detected jitting");232}233} else {234long[] iWalkback = (long[])walkback;235if (PC == 0) {236PC = iWalkback[0];237} else if (PC != iWalkback[0]) {238throw new JittingDetector("detected jitting");239}240}241}242}243244245