Path: blob/master/test/jdk/java/lang/invoke/InvokeDynamicPrintArgs.java
41149 views
/*1* Copyright (c) 2010, 2019, 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/* @test24* @bug 7050328 800703525* @summary smoke test for invokedynamic instructions26* @build indify.Indify27* @compile InvokeDynamicPrintArgs.java28* @run main/othervm29* indify.Indify30* --verify-specifier-count=831* --expand-properties --classpath ${test.classes}32* --java test.java.lang.invoke.InvokeDynamicPrintArgs --check-output33* @run main/othervm34* -Djava.security.manager=allow35* indify.Indify36* --expand-properties --classpath ${test.classes}37* --java test.java.lang.invoke.InvokeDynamicPrintArgs --security-manager38*/3940package test.java.lang.invoke;4142import java.util.*;43import java.io.*;4445import java.lang.invoke.*;46import java.security.*;47import static java.lang.invoke.MethodHandles.*;48import static java.lang.invoke.MethodType.*;4950public class InvokeDynamicPrintArgs {51public static void main(String... av) throws Throwable {52if (av.length > 0 && av[0].equals("--check-output")) openBuf();53if (av.length > 0 && av[0].equals("--security-manager")) setSM();54System.out.println("Printing some argument lists, starting with a empty one:");55INDY_nothing().invokeExact(); // BSM specifier #0 = {bsm}56INDY_bar().invokeExact("bar arg", 1); // BSM specifier #1 = {bsm2, Void.class, "void type"}57INDY_bar2().invokeExact("bar2 arg", 222); // BSM specifier #1 = (same)58INDY_baz().invokeExact("baz arg", 2, 3.14); // BSM specifier #2 = {bsm2, 1234.5}59INDY_foo().invokeExact("foo arg"); // BSM specifier #0 = (same)60// Hence, BSM specifier count should be 3. See "--verify-specifier-count=3" above.61System.out.println("Done printing argument lists.");62closeBuf();63checkConstantRefs();64}6566private static void checkConstantRefs() throws Throwable {67// check some constant references to its self class68assertEquals(MT_bsm(), MH_bsm().type());69assertEquals(MT_bsm2(), MH_bsm2().type());70assertEquals(MT_bsm(), non_MH_bsm().type());71}72private static void assertEquals(Object exp, Object act) {73if (exp == act || (exp != null && exp.equals(act))) return;74throw new AssertionError("not equal: "+exp+", "+act);75}7677private static void setSM() {78Policy.setPolicy(new TestPolicy());79System.setSecurityManager(new SecurityManager());80}8182private static PrintStream oldOut;83private static ByteArrayOutputStream buf;84private static void openBuf() {85oldOut = System.out;86buf = new ByteArrayOutputStream();87System.setOut(new PrintStream(buf));88}89private static void closeBuf() {90if (buf == null) return;91System.out.flush();92System.setOut(oldOut);93String[] haveLines = new String(buf.toByteArray()).split("[\n\r]+");94for (String line : haveLines) System.out.println(line);95Iterator<String> iter = Arrays.asList(haveLines).iterator();96for (String want : EXPECT_OUTPUT) {97String have = iter.hasNext() ? iter.next() : "[EOF]";98if (want.equals(have)) continue;99System.err.println("want line: "+want);100System.err.println("have line: "+have);101throw new AssertionError("unexpected output: "+have);102}103if (iter.hasNext())104throw new AssertionError("unexpected output: "+iter.next());105}106private static final String[] EXPECT_OUTPUT = {107"Printing some argument lists, starting with a empty one:",108"[test.java.lang.invoke.InvokeDynamicPrintArgs, nothing, ()void][]",109"[test.java.lang.invoke.InvokeDynamicPrintArgs, bar, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar arg, 1]",110"[test.java.lang.invoke.InvokeDynamicPrintArgs, bar2, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar2 arg, 222]",111"[test.java.lang.invoke.InvokeDynamicPrintArgs, baz, (String,int,double)void, 1234.5][baz arg, 2, 3.14]",112"[test.java.lang.invoke.InvokeDynamicPrintArgs, foo, (String)void][foo arg]",113"Done printing argument lists."114};115116private static boolean doPrint = true;117private static void printArgs(Object bsmInfo, Object... args) {118String message = bsmInfo+Arrays.deepToString(args);119if (doPrint) System.out.println(message);120}121private static MethodHandle MH_printArgs() throws ReflectiveOperationException {122shouldNotCallThis();123return lookup().findStatic(lookup().lookupClass(),124"printArgs", methodType(void.class, Object.class, Object[].class));125}126127private static CallSite bsm(Lookup caller, String name, MethodType type) throws ReflectiveOperationException {128// ignore caller and name, but match the type:129Object bsmInfo = Arrays.asList(caller, name, type);130return new ConstantCallSite(MH_printArgs().bindTo(bsmInfo).asCollector(Object[].class, type.parameterCount()).asType(type));131}132private static MethodType MT_bsm() {133shouldNotCallThis();134return methodType(CallSite.class, Lookup.class, String.class, MethodType.class);135}136private static MethodHandle MH_bsm() throws ReflectiveOperationException {137shouldNotCallThis();138return lookup().findStatic(lookup().lookupClass(), "bsm", MT_bsm());139}140private static MethodHandle non_MH_bsm() throws ReflectiveOperationException {141return lookup().findStatic(lookup().lookupClass(), "bsm", MT_bsm());142}143144/* Example of a constant call site with user-data.145* In this case, the user data is exactly the BSM data.146* Note that a CCS with user data must use the "hooked" constructor147* to bind the CCS itself into the resulting target.148* A normal constructor would not allow a circular relation149* between the CCS and its target.150*/151public static class PrintingCallSite extends ConstantCallSite {152final Lookup caller;153final String name;154final Object[] staticArgs;155156PrintingCallSite(Lookup caller, String name, MethodType type, Object... staticArgs) throws Throwable {157super(type, MH_createTarget());158this.caller = caller;159this.name = name;160this.staticArgs = staticArgs;161}162163public MethodHandle createTarget() {164try {165return lookup().bind(this, "runTarget", genericMethodType(0, true)).asType(type());166} catch (ReflectiveOperationException ex) {167throw new RuntimeException(ex);168}169}170171public Object runTarget(Object... dynamicArgs) {172List<Object> bsmInfo = new ArrayList<>(Arrays.asList(caller, name, type()));173bsmInfo.addAll(Arrays.asList(staticArgs));174printArgs(bsmInfo, dynamicArgs);175return null;176}177178private static MethodHandle MH_createTarget() throws ReflectiveOperationException {179shouldNotCallThis();180return lookup().findVirtual(lookup().lookupClass(), "createTarget", methodType(MethodHandle.class));181}182}183private static CallSite bsm2(Lookup caller, String name, MethodType type, Object... arg) throws Throwable {184// ignore caller and name, but match the type:185return new PrintingCallSite(caller, name, type, arg);186}187private static MethodType MT_bsm2() {188shouldNotCallThis();189return methodType(CallSite.class, Lookup.class, String.class, MethodType.class, Object[].class);190}191private static MethodHandle MH_bsm2() throws ReflectiveOperationException {192shouldNotCallThis();193return lookup().findStatic(lookup().lookupClass(), "bsm2", MT_bsm2());194}195196private static MethodHandle INDY_nothing() throws Throwable {197shouldNotCallThis();198return ((CallSite) MH_bsm().invoke(lookup(),199"nothing", methodType(void.class)200)).dynamicInvoker();201}202private static MethodHandle INDY_foo() throws Throwable {203shouldNotCallThis();204return ((CallSite) MH_bsm().invoke(lookup(),205"foo", methodType(void.class, String.class)206)).dynamicInvoker();207}208private static MethodHandle INDY_bar() throws Throwable {209shouldNotCallThis();210return ((CallSite) MH_bsm2().invoke(lookup(),211"bar", methodType(void.class, String.class, int.class)212, Void.class, "void type!", 1, 234.5F, 67.5, (long)89213)).dynamicInvoker();214}215private static MethodHandle INDY_bar2() throws Throwable {216shouldNotCallThis();217return ((CallSite) MH_bsm2().invoke(lookup(),218"bar2", methodType(void.class, String.class, int.class)219, Void.class, "void type!", 1, 234.5F, 67.5, (long)89220)).dynamicInvoker();221}222private static MethodHandle INDY_baz() throws Throwable {223shouldNotCallThis();224return ((CallSite) MH_bsm2().invoke(lookup(),225"baz", methodType(void.class, String.class, int.class, double.class)226, 1234.5227)).dynamicInvoker();228}229230private static void shouldNotCallThis() {231// if this gets called, the transformation has not taken place232if (System.getProperty("InvokeDynamicPrintArgs.allow-untransformed") != null) return;233throw new AssertionError("this code should be statically transformed away by Indify");234}235236static class TestPolicy extends Policy {237static final Policy DEFAULT_POLICY = Policy.getPolicy();238239final PermissionCollection permissions = new Permissions();240TestPolicy() {241permissions.add(new java.io.FilePermission("<<ALL FILES>>", "read"));242}243public PermissionCollection getPermissions(ProtectionDomain domain) {244return permissions;245}246247public PermissionCollection getPermissions(CodeSource codesource) {248return permissions;249}250251public boolean implies(ProtectionDomain domain, Permission perm) {252return permissions.implies(perm) || DEFAULT_POLICY.implies(domain, perm);253}254}255}256257258