jdk/test/java/lang/instrument/RetransformAgent.java
changeset 2 90ce3da70b43
child 277 9d9c1747de00
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/instrument/RetransformAgent.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6274264 6274241 5070281
+ * @summary test retransformClasses
+ * @author Robert Field, Sun Microsystems
+ *
+ * @run shell MakeJAR2.sh RetransformAgent RetransformApp 'Can-Retransform-Classes: true'
+ * @run main/othervm -javaagent:RetransformAgent.jar RetransformApp
+ */
+
+import java.lang.instrument.*;
+import java.security.ProtectionDomain;
+import java.io.*;
+
+import ilib.*;
+
+class RetransformAgent {
+
+    static ClassFileTransformer t1, t2, t3, t4;
+    static Instrumentation inst;
+    static boolean succeeded = true;
+    static int markCount = 0;
+    static int[] markGolden = {30, 40, 20, 30, 40, 20, 30, 40, 20, 30, 40, 20,
+                               11, 40, 20, 11, 40, 20, 11, 40, 20, 11, 40, 20};
+
+    static class Tr implements ClassFileTransformer {
+        final String trname;
+        final boolean onLoad;
+        final int loadIndex;
+        final boolean onRedef;
+        final int redefIndex;
+        final String cname;
+        final String nname;
+
+        Tr(String trname, boolean onLoad, int loadIndex, boolean onRedef, int redefIndex,
+           String cname, String nname) {
+            this.trname = trname;
+            this.onLoad = onLoad;
+            this.loadIndex = loadIndex;
+            this.onRedef = onRedef;
+            this.redefIndex = redefIndex;
+            this.cname = cname;
+            this.nname = nname;
+        }
+
+        public byte[] transform(ClassLoader loader,
+                                String className,
+                                Class<?> classBeingRedefined,
+                                ProtectionDomain    protectionDomain,
+                                byte[] classfileBuffer) {
+            boolean redef = classBeingRedefined != null;
+            // System.err.println("hook " + trname + ": " + className +
+            //                    (redef? " REDEF" : " LOAD"));
+            if ((redef? onRedef : onLoad) && className != null && className.equals(cname)) {
+                Options opt = new Options();
+                opt.shouldInstrumentIndexed = true;
+                opt.shouldInstrumentCall = true;
+                opt.targetMethod = nname;
+                opt.fixedIndex = redef? redefIndex : loadIndex;
+                opt.trackerClassName = "RetransformAgent";
+                try {
+                    byte[] newcf =  Inject.instrumentation(opt, loader, className, classfileBuffer);
+                    /*** debugging ...
+                         String fname = trname + (redef?"_redef" : "");
+                         write_buffer(fname + "_before.class", classfileBuffer);
+                         write_buffer(fname + "_instr.class", newcf);
+                    ***/
+                    System.err.println(trname + ": " + className + " index: " + opt.fixedIndex +
+                                       (redef? " REDEF" : " LOAD") +
+                                       " len before: " + classfileBuffer.length +
+                                       " after: " + newcf.length);
+                    return newcf;
+                } catch (Throwable ex) {
+                    System.err.println("Injection failure: " + ex);
+                    ex.printStackTrace();
+                }
+            }
+            return null;
+        }
+    }
+
+    static void write_buffer(String fname, byte[]buffer) {
+        try {
+            FileOutputStream outStream = new FileOutputStream(fname);
+            outStream.write(buffer, 0, buffer.length);
+            outStream.close();
+        } catch (Exception ex) {
+            System.err.println("EXCEPTION in write_buffer: " + ex);
+        }
+    }
+
+    public static void premain (String agentArgs, Instrumentation instArg) {
+        inst = instArg;
+        System.err.println("Premain");
+
+        t1 = new Tr("TR1", false, 10, true, 11, "RetransformApp", "foo");
+        inst.addTransformer(t1, true);
+        t2 = new Tr("TN2", true,  20, true, 21, "RetransformApp", "foo");
+        inst.addTransformer(t2, false);
+        t3 = new Tr("TR3", true,  30, true, 31, "RetransformApp", "foo");
+        inst.addTransformer(t3, true);
+        t4 = new Tr("TN4", true,  40, true, 41, "RetransformApp", "foo");
+        inst.addTransformer(t4, false);
+    }
+
+    public static void undo() {
+        inst.removeTransformer(t3);
+        try {
+            System.err.println("RETRANSFORM");
+            inst.retransformClasses(new RetransformApp().getClass());
+        } catch (Exception ex) {
+            System.err.println("EXCEPTION on undo: " + ex);
+        }
+    }
+
+    public static boolean succeeded() {
+        return succeeded && markCount == markGolden.length;
+    }
+
+    public static void callTracker(int mark) {
+        System.err.println("got mark " + mark);
+        if (markCount >= markGolden.length || mark != markGolden[markCount++]) {
+            succeeded = false;
+        }
+    }
+}