Path: blob/master/test/hotspot/jtreg/runtime/BootstrapMethod/BSMCalledTwice.java
40942 views
/*1* Copyright (c) 2017, 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 817495426* @library /test/lib27* @modules java.base/jdk.internal.org.objectweb.asm28* @compile -XDignore.symbol.file BSMCalledTwice.java29* @run main BSMCalledTwice30*/3132import java.io.File;33import java.io.FileOutputStream;34import java.util.*;35import static jdk.internal.org.objectweb.asm.Opcodes.*;36import jdk.internal.org.objectweb.asm.*;37import jdk.test.lib.process.ProcessTools;38import jdk.test.lib.process.OutputAnalyzer;3940// BSMCalledTwice generates a class file named "TestC.class" that contains41// bytecodes that represent the following program42//43// public class TestC {44// public static void main(java.lang.String[] arg) {45// for (int i=0; i < 2; i++) {46// try {47// String f = "friend";48//49// // The "hello " + f in the following statement produces an50// // invokedynamic with a BSM of51// // StringConcatFactory.java/makeConcatWithConstants.52// // The ASM below erroneously puts 2 static arguments, "hello "53// // and "goodbye" on the stack for the BSM. Causing a exception to54// // be thrown when creatingthe CallSite object.55// System.out.println("hello " + f); <--------------- invokedynamic56//57// } catch (Error e) {58// System.out.println("Caught Error:");59// System.out.println(e.getMessage());60// e.printStackTrace();61// }62// }63// }64// }65//66public class BSMCalledTwice implements Opcodes {67static final String classTestCName = "TestC";6869public static int count_makeSite(String text) {70int count = 0;71String text_ptr = text;72while (text_ptr.indexOf("makeSite") != -1) {73text_ptr = text_ptr.substring(text_ptr.indexOf("makeSite") + 1);74count++;75}76return count;77}7879public static void main(String[] args) throws Exception {80ClassLoader cl = new ClassLoader() {81public Class<?> loadClass(String name) throws ClassNotFoundException {82if (findLoadedClass(name) != null) {83return findLoadedClass(name);84}8586if (classTestCName.equals(name)) {87byte[] classFile = null;88try {89classFile = dumpTestC();90} catch (Exception e) {91}92return defineClass(classTestCName, classFile, 0, classFile.length);93}94return super.loadClass(name);95}96};9798cl.loadClass(classTestCName);99ProcessBuilder pb = ProcessTools.createTestJvm("-cp", ".", classTestCName);100OutputAnalyzer output = new OutputAnalyzer(pb.start());101String test_output = output.getOutput();102if (test_output == null) {103throw new RuntimeException("Test failed, null test output");104}105// "makeSite" is currently listed twice in the exception stacks for each106// failing call to the BootstrapMethod. So more that two calls means107// that the BootstrapMethod was called more than once.108int count = count_makeSite(test_output);109if (count < 1 || count > 2) {110throw new RuntimeException("Test failed, bad number of calls to BootstrapMethod");111}112output.shouldHaveExitValue(0);113}114115public static byte[] dumpTestC () throws Exception {116ClassWriter cw = new ClassWriter(0);117FieldVisitor fv;118MethodVisitor mv;119AnnotationVisitor av0;120121cw.visit(53, ACC_PUBLIC + ACC_SUPER, classTestCName, null, "java/lang/Object", null);122123cw.visitInnerClass("java/lang/invoke/MethodHandles$Lookup",124"java/lang/invoke/MethodHandles", "Lookup",125ACC_PUBLIC + ACC_FINAL + ACC_STATIC);126127{128mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);129mv.visitCode();130mv.visitVarInsn(ALOAD, 0);131mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);132mv.visitInsn(RETURN);133mv.visitMaxs(1, 1);134mv.visitEnd();135}136{137mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);138mv.visitCode();139Label l0 = new Label();140Label l1 = new Label();141Label l2 = new Label();142mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Error");143mv.visitInsn(ICONST_0);144mv.visitVarInsn(ISTORE, 1);145Label l3 = new Label();146mv.visitLabel(l3);147mv.visitFrame(Opcodes.F_APPEND,1, new Object[] {Opcodes.INTEGER}, 0, null);148mv.visitVarInsn(ILOAD, 1);149mv.visitInsn(ICONST_2);150Label l4 = new Label();151mv.visitJumpInsn(IF_ICMPGE, l4);152mv.visitLabel(l0);153mv.visitLdcInsn("friend");154mv.visitVarInsn(ASTORE, 2);155mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");156mv.visitVarInsn(ALOAD, 2);157mv.visitInvokeDynamicInsn("makeConcatWithConstants",158"(Ljava/lang/String;)Ljava/lang/String;",159new Handle(Opcodes.H_INVOKESTATIC,160"java/lang/invoke/StringConcatFactory",161"makeConcatWithConstants",162"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;"),163new Object[]{"hello \u0001", "goodbye"});164mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);165mv.visitLabel(l1);166Label l5 = new Label();167mv.visitJumpInsn(GOTO, l5);168mv.visitLabel(l2);169mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/Error"});170mv.visitVarInsn(ASTORE, 2);171mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");172mv.visitLdcInsn("Caught Error:");173mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);174mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");175mv.visitVarInsn(ALOAD, 2);176mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Error", "getMessage", "()Ljava/lang/String;", false);177mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);178mv.visitVarInsn(ALOAD, 2);179mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Error", "printStackTrace", "()V", false);180mv.visitLabel(l5);181mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);182mv.visitIincInsn(1, 1);183mv.visitJumpInsn(GOTO, l3);184mv.visitLabel(l4);185mv.visitFrame(Opcodes.F_CHOP,1, null, 0, null);186mv.visitInsn(RETURN);187mv.visitMaxs(2, 3);188mv.visitEnd();189}190cw.visitEnd();191192try(FileOutputStream fos = new FileOutputStream(new File("TestC.class"))) {193fos.write(cw.toByteArray());194}195return cw.toByteArray();196}197}198199200