Path: blob/master/test/hotspot/jtreg/runtime/HiddenClasses/HiddenDefMeths.java
40942 views
/*1* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @summary Tests a hidden class that implements interfaces with default methods.26* @library /testlibrary27* @modules java.base/jdk.internal.org.objectweb.asm28* java.management29* @run main HiddenDefMeths30*/3132import jdk.internal.org.objectweb.asm.ClassWriter;33import jdk.internal.org.objectweb.asm.MethodVisitor;34import jdk.internal.org.objectweb.asm.Type;3536import java.lang.invoke.MethodType;37import java.lang.invoke.MethodHandles;38import java.lang.invoke.MethodHandles.Lookup;39import static java.lang.invoke.MethodHandles.Lookup.ClassOption.*;40import java.lang.reflect.Field;41import java.lang.reflect.Method;42import java.util.stream.Collectors;43import java.util.stream.Stream;4445import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PRIVATE;46import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;47import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;48import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD;49import static jdk.internal.org.objectweb.asm.Opcodes.ARETURN;50import static jdk.internal.org.objectweb.asm.Opcodes.DUP;51import static jdk.internal.org.objectweb.asm.Opcodes.GETFIELD;52import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL;53import static jdk.internal.org.objectweb.asm.Opcodes.PUTFIELD;54import static jdk.internal.org.objectweb.asm.Opcodes.RETURN;55import static jdk.internal.org.objectweb.asm.Opcodes.V1_8;5657public class HiddenDefMeths {5859interface Resource {60Pointer ptr();61}6263interface Struct extends Resource {64StructPointer ptr();65}6667interface Pointer { }6869interface StructPointer extends Pointer { }7071interface I extends Struct {72void m();73}7475static String IMPL_PREFIX = "$$impl";76static String PTR_FIELD_NAME = "ptr";7778// Generate a class similar to:79//80// public class HiddenDefMeths$I$$impl implements HiddenDefMeths$I, HiddenDefMeths$Struct {81//82// public HiddenDefMeths$StructPointer ptr;83//84// public HiddenDefMeths$I$$impl(HiddenDefMeths$StructPointer p) {85// ptr = p;86// }87//88// public HiddenDefMeths$StructPointer ptr() {89// return ptr;90// }91// }92//93byte[] generate(Class<?> iface) {94ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);9596String ifaceTypeName = Type.getInternalName(iface);97String proxyClassName = ifaceTypeName + IMPL_PREFIX;98// class definition99cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, proxyClassName,100desc(Object.class) + desc(ifaceTypeName) + desc(Struct.class),101name(Object.class),102new String[] { ifaceTypeName, name(Struct.class) });103104cw.visitField(ACC_PUBLIC, PTR_FIELD_NAME, desc(StructPointer.class), desc(StructPointer.class), null);105cw.visitEnd();106107// constructor108MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>",109meth(desc(void.class), desc(StructPointer.class)),110meth(desc(void.class), desc(StructPointer.class)), null);111mv.visitCode();112mv.visitVarInsn(ALOAD, 0);113mv.visitInsn(DUP);114mv.visitMethodInsn(INVOKESPECIAL, name(Object.class), "<init>", meth(desc(void.class)), false);115mv.visitVarInsn(ALOAD, 1);116// Execution of this PUTFIELD instruction causes the bug's ClassNotFoundException.117mv.visitFieldInsn(PUTFIELD, proxyClassName, PTR_FIELD_NAME, desc(StructPointer.class));118mv.visitInsn(RETURN);119mv.visitMaxs(0, 0);120mv.visitEnd();121122// ptr() impl123mv = cw.visitMethod(ACC_PUBLIC, PTR_FIELD_NAME, meth(desc(StructPointer.class)),124meth(desc(StructPointer.class)), null);125mv.visitCode();126mv.visitVarInsn(ALOAD, 0);127mv.visitFieldInsn(GETFIELD, proxyClassName, PTR_FIELD_NAME, desc(StructPointer.class));128mv.visitInsn(ARETURN);129mv.visitMaxs(0, 0);130mv.visitEnd();131132return cw.toByteArray();133}134135String name(Class<?> clazz) {136if (clazz.isPrimitive()) {137throw new IllegalStateException();138} else if (clazz.isArray()) {139return desc(clazz);140} else {141return clazz.getName().replaceAll("\\.", "/");142}143}144145String desc(Class<?> clazz) {146String mdesc = MethodType.methodType(clazz).toMethodDescriptorString();147return mdesc.substring(mdesc.indexOf(')') + 1);148}149150String desc(String clazzName) {151return "L" + clazzName + ";";152}153154String gen(String clazz, String... typeargs) {155return clazz.substring(0, clazz.length() - 1) + Stream.of(typeargs).collect(Collectors.joining("", "<", ">")) + ";";156}157158String meth(String restype, String... argtypes) {159return Stream.of(argtypes).collect(Collectors.joining("", "(", ")")) + restype;160}161162String meth(Method m) {163return MethodType.methodType(m.getReturnType(), m.getParameterTypes()).toMethodDescriptorString();164}165166public static void main(String[] args) throws Throwable {167byte[] bytes = new HiddenDefMeths().generate(I.class);168Lookup lookup = MethodHandles.lookup();169Class<?> cl = lookup.defineHiddenClass(bytes, false, NESTMATE).lookupClass();170I i = (I)cl.getConstructors()[0].newInstance(new Object[] { null });171}172}173174175