1/* 2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/** 25 * @test 26 * @bug 8008678 27 * @summary JSR 292: constant pool reconstitution must support pseudo strings 28 * @library /test/lib 29 * @modules java.base/jdk.internal.misc 30 * java.instrument 31 * java.management 32 * jdk.jartool/sun.tools.jar 33 * @compile -XDignore.symbol.file TestLambdaFormRetransformation.java 34 * @run main TestLambdaFormRetransformation 35 */ 36 37import java.io.IOException; 38import java.lang.instrument.ClassFileTransformer; 39import java.lang.instrument.IllegalClassFormatException; 40import java.lang.instrument.Instrumentation; 41import java.lang.instrument.UnmodifiableClassException; 42import java.nio.file.Files; 43import java.nio.file.Path; 44import java.nio.file.Paths; 45import java.security.ProtectionDomain; 46import java.util.Arrays; 47 48import jdk.test.lib.process.ExitCode; 49import jdk.test.lib.process.OutputAnalyzer; 50import jdk.test.lib.process.ProcessTools; 51 52public class TestLambdaFormRetransformation { 53 private static String MANIFEST = String.format("Manifest-Version: 1.0\n" + 54 "Premain-Class: %s\n" + 55 "Can-Retransform-Classes: true\n", 56 Agent.class.getName()); 57 58 private static String CP = System.getProperty("test.classes"); 59 60 public static void main(String args[]) throws Throwable { 61 Path agent = TestLambdaFormRetransformation.buildAgent(); 62 OutputAnalyzer oa = ProcessTools.executeTestJvm("-javaagent:" + 63 agent.toAbsolutePath().toString(), "-version"); 64 oa.shouldHaveExitValue(ExitCode.OK.value); 65 } 66 67 private static Path buildAgent() throws IOException { 68 Path manifest = TestLambdaFormRetransformation.createManifest(); 69 Path jar = Files.createTempFile(Paths.get("."), null, ".jar"); 70 71 String[] args = new String[] { 72 "-cfm", 73 jar.toAbsolutePath().toString(), 74 manifest.toAbsolutePath().toString(), 75 "-C", 76 TestLambdaFormRetransformation.CP, 77 Agent.class.getName() + ".class" 78 }; 79 80 sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar"); 81 82 if (!jarTool.run(args)) { 83 throw new Error("jar failed: args=" + Arrays.toString(args)); 84 } 85 return jar; 86 } 87 88 private static Path createManifest() throws IOException { 89 Path manifest = Files.createTempFile(Paths.get("."), null, ".mf"); 90 byte[] manifestBytes = TestLambdaFormRetransformation.MANIFEST.getBytes(); 91 Files.write(manifest, manifestBytes); 92 return manifest; 93 } 94} 95 96class Agent implements ClassFileTransformer { 97 private static Runnable lambda = () -> { 98 System.out.println("I'll crash you!"); 99 }; 100 101 public static void premain(String args, Instrumentation instrumentation) { 102 if (!instrumentation.isRetransformClassesSupported()) { 103 System.out.println("Class retransformation is not supported."); 104 return; 105 } 106 System.out.println("Calling lambda to ensure that lambda forms were created"); 107 108 Agent.lambda.run(); 109 110 System.out.println("Registering class file transformer"); 111 112 instrumentation.addTransformer(new Agent()); 113 114 for (Class c : instrumentation.getAllLoadedClasses()) { 115 if (c.getName().contains("LambdaForm") && 116 instrumentation.isModifiableClass(c)) { 117 System.out.format("We've found a modifiable lambda form: %s%n", c.getName()); 118 try { 119 instrumentation.retransformClasses(c); 120 } catch (UnmodifiableClassException e) { 121 throw new AssertionError("Modification of modifiable class " + 122 "caused UnmodifiableClassException", e); 123 } 124 } 125 } 126 } 127 128 public static void main(String args[]) { 129 } 130 131 @Override 132 public byte[] transform(ClassLoader loader, 133 String className, 134 Class<?> classBeingRedefined, 135 ProtectionDomain protectionDomain, 136 byte[] classfileBuffer 137 ) throws IllegalClassFormatException { 138 System.out.println("Transforming " + className); 139 return classfileBuffer.clone(); 140 } 141} 142