1 /* 2 * Copyright (c) 2005, 2015, 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 6274264 6274241 5070281 27 * @summary test retransformClasses 28 * @author Robert Field, Sun Microsystems 29 * 30 * @modules java.base/jdk.internal.org.objectweb.asm 31 * @run shell/timeout=240 MakeJAR2.sh RetransformAgent RetransformApp 'Can-Retransform-Classes: true' 32 * @run main/othervm -javaagent:RetransformAgent.jar RetransformApp 33 */ 34 35 import java.lang.instrument.*; 36 import java.security.ProtectionDomain; 37 import java.io.*; 38 import asmlib.*; 39 40 class RetransformAgent { 41 42 static ClassFileTransformer t1, t2, t3, t4; 43 static Instrumentation inst; 44 static boolean succeeded = true; 45 static int markCount = 0; 46 static int[] markGolden = {30, 40, 20, 30, 40, 20, 30, 40, 20, 30, 40, 20, 47 11, 40, 20, 11, 40, 20, 11, 40, 20, 11, 40, 20}; 48 49 static class Tr implements ClassFileTransformer { 50 final String trname; 51 final boolean onLoad; 52 final int loadIndex; 53 final boolean onRedef; 54 final int redefIndex; 55 final String cname; 56 final String nname; 57 58 Tr(String trname, boolean onLoad, int loadIndex, boolean onRedef, int redefIndex, 59 String cname, String nname) { 60 this.trname = trname; 61 this.onLoad = onLoad; 62 this.loadIndex = loadIndex; 63 this.onRedef = onRedef; 64 this.redefIndex = redefIndex; 65 this.cname = cname; 66 this.nname = nname; 67 } 68 69 public byte[] transform(ClassLoader loader, 70 String className, 71 Class<?> classBeingRedefined, 72 ProtectionDomain protectionDomain, 73 byte[] classfileBuffer) { 74 boolean redef = classBeingRedefined != null; 75 // System.err.println("hook " + trname + ": " + className + 76 // (redef? " REDEF" : " LOAD")); 77 if ((redef? onRedef : onLoad) && className != null && className.equals(cname)) { 78 int fixedIndex = redef ? redefIndex : loadIndex; 79 try { 80 byte[] newcf = Instrumentor.instrFor(classfileBuffer) 81 .addMethodEntryInjection( 82 nname, 83 (h)->{ 84 h.push(fixedIndex); 85 h.invokeStatic("RetransformAgent", "callTracker", "(I)V", false); 86 }) 87 .apply(); 88 /*** debugging ... 89 if (newcf != null) { 90 String fname = trname + (redef?"_redef" : "") + "/" + className; 91 System.err.println("dumping to: " + fname); 92 write_buffer(fname + "_before.class", classfileBuffer); 93 write_buffer(fname + "_instr.class", newcf); 94 } 95 ***/ 96 System.err.println(trname + ": " + className + " index: " + fixedIndex + 97 (redef? " REDEF" : " LOAD") + 98 " len before: " + classfileBuffer.length + 99 " after: " + newcf.length); 100 return newcf; 101 } catch (Throwable ex) { 102 System.err.println("Injection failure: " + ex); 103 ex.printStackTrace(); 104 } 105 } 106 return null; 107 } 108 } 109 110 static void write_buffer(String fname, byte[]buffer) { 111 try { 112 File f = new File(fname); 113 if (!f.getParentFile().exists()) { 114 f.getParentFile().mkdirs(); 115 } 116 try (FileOutputStream outStream = new FileOutputStream(f)) { 117 outStream.write(buffer, 0, buffer.length); 118 } 119 } catch (IOException ex) { 120 System.err.println("EXCEPTION in write_buffer: " + ex); 121 } 122 } 123 124 public static void premain (String agentArgs, Instrumentation instArg) { 125 inst = instArg; 126 System.err.println("Premain"); 127 128 t1 = new Tr("TR1", false, 10, true, 11, "RetransformApp", "foo"); 129 inst.addTransformer(t1, true); 130 t2 = new Tr("TN2", true, 20, true, 21, "RetransformApp", "foo"); 131 inst.addTransformer(t2, false); 132 t3 = new Tr("TR3", true, 30, true, 31, "RetransformApp", "foo"); 133 inst.addTransformer(t3, true); 134 t4 = new Tr("TN4", true, 40, true, 41, "RetransformApp", "foo"); 135 inst.addTransformer(t4, false); 136 } 137 138 public static void undo() { 139 inst.removeTransformer(t3); 140 try { 141 System.err.println("RETRANSFORM"); 142 inst.retransformClasses(new RetransformApp().getClass()); 143 } catch (Exception ex) { 144 System.err.println("EXCEPTION on undo: " + ex); 145 } 146 } 147 148 public static boolean succeeded() { 149 return succeeded && markCount == markGolden.length; 150 } 151 152 public static void callTracker(int mark) { 153 System.err.println("got mark " + mark); 154 if (markCount >= markGolden.length || mark != markGolden[markCount++]) { 155 succeeded = false; 156 } 157 } 158 }