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