Path: blob/jdk8u272-b10-aarch32-20201026/jdk/test/java/lang/invoke/lambda/LambdaAsm.java
48795 views
/*1* Copyright (c) 2013, 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* @bug 802723226* @summary ensures that j.l.i.InvokerByteCodeGenerator and ASM visitMethodInsn27* generate bytecodes with correct constant pool references28* @compile -XDignore.symbol.file LambdaAsm.java LUtils.java29* @run main/othervm LambdaAsm30*/31import com.sun.tools.classfile.Attribute;32import com.sun.tools.classfile.ClassFile;33import com.sun.tools.classfile.Code_attribute;34import com.sun.tools.classfile.ConstantPool;35import com.sun.tools.classfile.ConstantPool.CPInfo;36import com.sun.tools.classfile.Instruction;37import com.sun.tools.classfile.Method;38import java.io.ByteArrayInputStream;39import java.io.File;40import java.util.ArrayList;41import java.nio.file.DirectoryStream;42import java.nio.file.Path;43import jdk.internal.org.objectweb.asm.ClassWriter;44import jdk.internal.org.objectweb.asm.MethodVisitor;4546import static java.nio.file.Files.*;47import static jdk.internal.org.objectweb.asm.Opcodes.*;4849public class LambdaAsm {5051static final File TestFile = new File("A.java");5253static void init() {54emitCode();55LUtils.compile(TestFile.getName());56LUtils.TestResult tr = LUtils.doExec(LUtils.JAVA_CMD.getAbsolutePath(),57"-Djdk.internal.lambda.dumpProxyClasses=.",58"-cp", ".", "A");59if (tr.exitValue != 0) {60System.out.println("Error: " + tr.toString());61throw new RuntimeException("could not create proxy classes");62}63}6465static void emitCode() {66ArrayList<String> scratch = new ArrayList<>();67scratch.add("import java.util.function.*;");68scratch.add("class A {");69scratch.add(" interface I {");70scratch.add(" default Supplier<Integer> a() { return () -> 1; }");71scratch.add(" default Supplier<Integer> b(int i) { return () -> i; }");72scratch.add(" default Supplier<Integer> c(int i) { return () -> m(i); }");73scratch.add(" int m(int i);");74scratch.add(" static Integer d() { return 0; }");75scratch.add(" }");76scratch.add(" static class C implements I {");77scratch.add(" public int m(int i) { return i;}");78scratch.add(" }");79scratch.add(" public static void main(String[] args) {");80scratch.add(" I i = new C();");81scratch.add(" i.a();");82scratch.add(" i.b(1);");83scratch.add(" i.c(1);");84scratch.add(" I.d();");85scratch.add(" }");86scratch.add("}");87LUtils.createFile(TestFile, scratch);88}8990static void checkMethod(String cname, String mname, ConstantPool cp,91Code_attribute code) throws ConstantPool.InvalidIndex {92for (Instruction i : code.getInstructions()) {93String iname = i.getMnemonic();94if ("invokespecial".equals(iname)95|| "invokestatic".equals(iname)) {96int idx = i.getByte(2);97System.out.println("Verifying " + cname + ":" + mname +98" instruction:" + iname + " index @" + idx);99CPInfo cpinfo = cp.get(idx);100if (cpinfo instanceof ConstantPool.CONSTANT_Methodref_info) {101throw new RuntimeException("unexpected CP type expected "102+ "InterfaceMethodRef, got MethodRef, " + cname103+ ", " + mname);104}105}106}107}108109static int checkMethod(ClassFile cf, String mthd) throws Exception {110if (cf.major_version < 52) {111throw new RuntimeException("unexpected class file version, in "112+ cf.getName() + "expected 52, got " + cf.major_version);113}114int count = 0;115for (Method m : cf.methods) {116String mname = m.getName(cf.constant_pool);117if (mname.equals(mthd)) {118for (Attribute a : m.attributes) {119if ("Code".equals(a.getName(cf.constant_pool))) {120count++;121checkMethod(cf.getName(), mname, cf.constant_pool,122(Code_attribute) a);123}124}125}126}127return count;128}129130static void verifyInvokerBytecodeGenerator() throws Exception {131int count = 0;132int mcount = 0;133try (DirectoryStream<Path> ds = newDirectoryStream(new File(".").toPath(),134// filter in lambda proxy classes135"A$I$$Lambda$?.class")) {136for (Path p : ds) {137System.out.println(p.toFile());138ClassFile cf = ClassFile.read(p.toFile());139// Check those methods implementing Supplier.get140mcount += checkMethod(cf, "get");141count++;142}143}144if (count < 3) {145throw new RuntimeException("unexpected number of files, "146+ "expected atleast 3 files, but got only " + count);147}148if (mcount < 3) {149throw new RuntimeException("unexpected number of methods, "150+ "expected atleast 3 methods, but got only " + mcount);151}152}153154static void verifyASM() throws Exception {155ClassWriter cw = new ClassWriter(0);156cw.visit(V1_8, ACC_PUBLIC, "X", null, "java/lang/Object", null);157MethodVisitor mv = cw.visitMethod(ACC_STATIC, "foo",158"()V", null, null);159mv.visitMaxs(2, 1);160mv.visitMethodInsn(INVOKESTATIC,161"java/util/function/Function.class",162"identity", "()Ljava/util/function/Function;", true);163mv.visitInsn(RETURN);164cw.visitEnd();165byte[] carray = cw.toByteArray();166// for debugging167// write((new File("X.class")).toPath(), carray, CREATE, TRUNCATE_EXISTING);168169// verify using javap/classfile reader170ClassFile cf = ClassFile.read(new ByteArrayInputStream(carray));171int mcount = checkMethod(cf, "foo");172if (mcount < 1) {173throw new RuntimeException("unexpected method count, expected 1" +174"but got " + mcount);175}176}177178public static void main(String... args) throws Exception {179init();180verifyInvokerBytecodeGenerator();181verifyASM();182}183}184185186