RetransformAgent.java revision 11884:b45c81ca8671
133965Sjdp/* 2218822Sdim * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. 3218822Sdim * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 460484Sobrien * 533965Sjdp * This code is free software; you can redistribute it and/or modify it 633965Sjdp * under the terms of the GNU General Public License version 2 only, as 733965Sjdp * published by the Free Software Foundation. 833965Sjdp * 933965Sjdp * This code is distributed in the hope that it will be useful, but WITHOUT 1033965Sjdp * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1133965Sjdp * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1233965Sjdp * version 2 for more details (a copy is included in the LICENSE file that 1333965Sjdp * accompanied this code). 1433965Sjdp * 1533965Sjdp * You should have received a copy of the GNU General Public License version 1633965Sjdp * 2 along with this work; if not, write to the Free Software Foundation, 1733965Sjdp * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1833965Sjdp * 1933965Sjdp * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20218822Sdim * or visit www.oracle.com if you need additional information or have any 21218822Sdim * questions. 2233965Sjdp */ 2333965Sjdp 2433965Sjdp/** 2533965Sjdp * @test 2660484Sobrien * @bug 6274264 6274241 5070281 27218822Sdim * @summary test retransformClasses 28218822Sdim * @author Robert Field, Sun Microsystems 29218822Sdim * 30218822Sdim * @modules java.base/jdk.internal.org.objectweb.asm 31218822Sdim * @run shell/timeout=240 MakeJAR2.sh RetransformAgent RetransformApp 'Can-Retransform-Classes: true' 32218822Sdim * @run main/othervm -javaagent:RetransformAgent.jar RetransformApp 33218822Sdim */ 34218822Sdim 35218822Sdimimport java.lang.instrument.*; 36218822Sdimimport java.security.ProtectionDomain; 37218822Sdimimport java.io.*; 38218822Sdimimport asmlib.*; 39218822Sdim 40218822Sdimclass RetransformAgent { 41218822Sdim 42218822Sdim static ClassFileTransformer t1, t2, t3, t4; 43218822Sdim static Instrumentation inst; 44218822Sdim static boolean succeeded = true; 45218822Sdim static int markCount = 0; 46218822Sdim static int[] markGolden = {30, 40, 20, 30, 40, 20, 30, 40, 20, 30, 40, 20, 47218822Sdim 11, 40, 20, 11, 40, 20, 11, 40, 20, 11, 40, 20}; 48218822Sdim 49218822Sdim static class Tr implements ClassFileTransformer { 50218822Sdim final String trname; 51218822Sdim final boolean onLoad; 52218822Sdim final int loadIndex; 53218822Sdim final boolean onRedef; 54218822Sdim final int redefIndex; 55218822Sdim final String cname; 56218822Sdim final String nname; 57218822Sdim 58218822Sdim Tr(String trname, boolean onLoad, int loadIndex, boolean onRedef, int redefIndex, 59218822Sdim String cname, String nname) { 60218822Sdim this.trname = trname; 61218822Sdim this.onLoad = onLoad; 62218822Sdim this.loadIndex = loadIndex; 6360484Sobrien this.onRedef = onRedef; 6460484Sobrien this.redefIndex = redefIndex; 6560484Sobrien this.cname = cname; 6660484Sobrien this.nname = nname; 6760484Sobrien } 6860484Sobrien 6960484Sobrien public byte[] transform(ClassLoader loader, 7060484Sobrien String className, 7160484Sobrien Class<?> classBeingRedefined, 7260484Sobrien ProtectionDomain protectionDomain, 7360484Sobrien byte[] classfileBuffer) { 7460484Sobrien boolean redef = classBeingRedefined != null; 7577298Sobrien // System.err.println("hook " + trname + ": " + className + 7677298Sobrien // (redef? " REDEF" : " LOAD")); 7777298Sobrien if ((redef? onRedef : onLoad) && className != null && className.equals(cname)) { 7877298Sobrien int fixedIndex = redef ? redefIndex : loadIndex; 7977298Sobrien try { 8060484Sobrien byte[] newcf = Instrumentor.instrFor(classfileBuffer) 8160484Sobrien .addMethodEntryInjection( 8260484Sobrien nname, 8360484Sobrien (h)->{ 8433965Sjdp h.push(fixedIndex); 8533965Sjdp h.invokeStatic("RetransformAgent", "callTracker", "(I)V", false); 8633965Sjdp }) 8733965Sjdp .apply(); 8833965Sjdp /*** debugging ... 8933965Sjdp if (newcf != null) { 9033965Sjdp String fname = trname + (redef?"_redef" : "") + "/" + className; 9133965Sjdp System.err.println("dumping to: " + fname); 9233965Sjdp write_buffer(fname + "_before.class", classfileBuffer); 9333965Sjdp write_buffer(fname + "_instr.class", newcf); 9433965Sjdp } 9560484Sobrien ***/ 9677298Sobrien System.err.println(trname + ": " + className + " index: " + fixedIndex + 9777298Sobrien (redef? " REDEF" : " LOAD") + 9877298Sobrien " len before: " + classfileBuffer.length + 9977298Sobrien " after: " + newcf.length); 10077298Sobrien return newcf; 10160484Sobrien } catch (Throwable ex) { 102218822Sdim System.err.println("Injection failure: " + ex); 10360484Sobrien ex.printStackTrace(); 104218822Sdim } 105218822Sdim } 106218822Sdim return null; 107218822Sdim } 108218822Sdim } 109218822Sdim 11077298Sobrien static void write_buffer(String fname, byte[]buffer) { 11160484Sobrien try { 11260484Sobrien File f = new File(fname); 113218822Sdim if (!f.getParentFile().exists()) { 11460484Sobrien f.getParentFile().mkdirs(); 11560484Sobrien } 11689857Sobrien try (FileOutputStream outStream = new FileOutputStream(f)) { 11789857Sobrien outStream.write(buffer, 0, buffer.length); 11889857Sobrien } 11989857Sobrien } catch (IOException ex) { 12089857Sobrien System.err.println("EXCEPTION in write_buffer: " + ex); 121218822Sdim } 122218822Sdim } 123218822Sdim 124218822Sdim public static void premain (String agentArgs, Instrumentation instArg) { 12533965Sjdp inst = instArg; 126218822Sdim System.err.println("Premain"); 127218822Sdim 128218822Sdim t1 = new Tr("TR1", false, 10, true, 11, "RetransformApp", "foo"); 129218822Sdim inst.addTransformer(t1, true); 130218822Sdim t2 = new Tr("TN2", true, 20, true, 21, "RetransformApp", "foo"); 131218822Sdim inst.addTransformer(t2, false); 132218822Sdim t3 = new Tr("TR3", true, 30, true, 31, "RetransformApp", "foo"); 133218822Sdim inst.addTransformer(t3, true); 134218822Sdim t4 = new Tr("TN4", true, 40, true, 41, "RetransformApp", "foo"); 13533965Sjdp inst.addTransformer(t4, false); 13633965Sjdp } 13733965Sjdp 13833965Sjdp public static void undo() { 13933965Sjdp inst.removeTransformer(t3); 14033965Sjdp try { 14133965Sjdp System.err.println("RETRANSFORM"); 14277298Sobrien inst.retransformClasses(new RetransformApp().getClass()); 14333965Sjdp } catch (Exception ex) { 144130561Sobrien System.err.println("EXCEPTION on undo: " + ex); 14589857Sobrien } 146104834Sobrien } 147130561Sobrien 148130561Sobrien public static boolean succeeded() { 14933965Sjdp return succeeded && markCount == markGolden.length; 150130561Sobrien } 15133965Sjdp 152130561Sobrien public static void callTracker(int mark) { 15333965Sjdp System.err.println("got mark " + mark); 154130561Sobrien if (markCount >= markGolden.length || mark != markGolden[markCount++]) { 155130561Sobrien succeeded = false; 15633965Sjdp } 157130561Sobrien } 158130561Sobrien} 15933965Sjdp