Path: blob/master/test/hotspot/jtreg/runtime/BootstrapMethod/BSMCalledTwice.java
64474 views
/*1* Copyright (c) 2017, 2021, 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*/3132/*33* @test34* @bug 826213435* @library /test/lib36* @requires vm.debug37* @modules java.base/jdk.internal.org.objectweb.asm38* @compile -XDignore.symbol.file BSMCalledTwice.java39* @run main/othervm -Xcomp -XX:CompileCommand=compileonly,TestC::* -XX:+DeoptimizeALot -XX:+VerifyStack BSMCalledTwice40*/4142import java.io.File;43import java.io.FileOutputStream;44import java.util.*;45import static jdk.internal.org.objectweb.asm.Opcodes.*;46import jdk.internal.org.objectweb.asm.*;47import jdk.test.lib.process.ProcessTools;48import jdk.test.lib.process.OutputAnalyzer;4950// BSMCalledTwice generates a class file named "TestC.class" that contains51// bytecodes that represent the following program52//53// public class TestC {54// public static void main(java.lang.String[] arg) {55// for (int i=0; i < 2; i++) {56// try {57// String f = "friend";58//59// // The "hello " + f in the following statement produces an60// // invokedynamic with a BSM of61// // StringConcatFactory.java/makeConcatWithConstants.62// // The ASM below erroneously puts 2 static arguments, "hello "63// // and "goodbye" on the stack for the BSM. Causing a exception to64// // be thrown when creatingthe CallSite object.65// System.out.println("hello " + f); <--------------- invokedynamic66//67// } catch (Error e) {68// System.out.println("Caught Error:");69// System.out.println(e.getMessage());70// e.printStackTrace();71// }72// }73// }74// }75//76public class BSMCalledTwice implements Opcodes {77static final String classTestCName = "TestC";7879public static int count_makeSite(String text) {80int count = 0;81String text_ptr = text;82while (text_ptr.indexOf("makeSite") != -1) {83text_ptr = text_ptr.substring(text_ptr.indexOf("makeSite") + 1);84count++;85}86return count;87}8889public static void main(String[] args) throws Exception {90ClassLoader cl = new ClassLoader() {91public Class<?> loadClass(String name) throws ClassNotFoundException {92if (findLoadedClass(name) != null) {93return findLoadedClass(name);94}9596if (classTestCName.equals(name)) {97byte[] classFile = null;98try {99classFile = dumpTestC();100} catch (Exception e) {101}102return defineClass(classTestCName, classFile, 0, classFile.length);103}104return super.loadClass(name);105}106};107108cl.loadClass(classTestCName);109ProcessBuilder pb = ProcessTools.createTestJvm("-cp", ".", classTestCName);110OutputAnalyzer output = new OutputAnalyzer(pb.start());111String test_output = output.getOutput();112if (test_output == null) {113throw new RuntimeException("Test failed, null test output");114}115// "makeSite" is currently listed twice in the exception stacks for each116// failing call to the BootstrapMethod. So more that two calls means117// that the BootstrapMethod was called more than once.118int count = count_makeSite(test_output);119if (count < 1 || count > 2) {120throw new RuntimeException("Test failed, bad number of calls to BootstrapMethod");121}122output.shouldHaveExitValue(0);123}124125public static byte[] dumpTestC () throws Exception {126ClassWriter cw = new ClassWriter(0);127FieldVisitor fv;128MethodVisitor mv;129AnnotationVisitor av0;130131cw.visit(53, ACC_PUBLIC + ACC_SUPER, classTestCName, null, "java/lang/Object", null);132133cw.visitInnerClass("java/lang/invoke/MethodHandles$Lookup",134"java/lang/invoke/MethodHandles", "Lookup",135ACC_PUBLIC + ACC_FINAL + ACC_STATIC);136137{138mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);139mv.visitCode();140mv.visitVarInsn(ALOAD, 0);141mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);142mv.visitInsn(RETURN);143mv.visitMaxs(1, 1);144mv.visitEnd();145}146{147mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);148mv.visitCode();149Label l0 = new Label();150Label l1 = new Label();151Label l2 = new Label();152mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Error");153mv.visitInsn(ICONST_0);154mv.visitVarInsn(ISTORE, 1);155Label l3 = new Label();156mv.visitLabel(l3);157mv.visitFrame(Opcodes.F_APPEND,1, new Object[] {Opcodes.INTEGER}, 0, null);158mv.visitVarInsn(ILOAD, 1);159mv.visitInsn(ICONST_2);160Label l4 = new Label();161mv.visitJumpInsn(IF_ICMPGE, l4);162mv.visitLabel(l0);163mv.visitLdcInsn("friend");164mv.visitVarInsn(ASTORE, 2);165mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");166mv.visitVarInsn(ALOAD, 2);167mv.visitInvokeDynamicInsn("makeConcatWithConstants",168"(Ljava/lang/String;)Ljava/lang/String;",169new Handle(Opcodes.H_INVOKESTATIC,170"java/lang/invoke/StringConcatFactory",171"makeConcatWithConstants",172"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;"),173new Object[]{"hello \u0001", "goodbye"});174mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);175mv.visitLabel(l1);176Label l5 = new Label();177mv.visitJumpInsn(GOTO, l5);178mv.visitLabel(l2);179mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/Error"});180mv.visitVarInsn(ASTORE, 2);181mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");182mv.visitLdcInsn("Caught Error:");183mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);184mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");185mv.visitVarInsn(ALOAD, 2);186mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Error", "getMessage", "()Ljava/lang/String;", false);187mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);188mv.visitVarInsn(ALOAD, 2);189mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Error", "printStackTrace", "()V", false);190mv.visitLabel(l5);191mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);192mv.visitIincInsn(1, 1);193mv.visitJumpInsn(GOTO, l3);194mv.visitLabel(l4);195mv.visitFrame(Opcodes.F_CHOP,1, null, 0, null);196mv.visitInsn(RETURN);197mv.visitMaxs(2, 3);198mv.visitEnd();199}200cw.visitEnd();201202try(FileOutputStream fos = new FileOutputStream(new File("TestC.class"))) {203fos.write(cw.toByteArray());204}205return cw.toByteArray();206}207}208209210