1 /*
2  * Copyright (c) 2006, 2013, 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  *
26  *
27  * @bug 6439234 6446941
28  *
29  * Test attach used in concert with transformers and redefineClasses.
30  *
31  * 6439234 java.lang.instrument: 8 JCK JPLIS tests fail when running in Live phase (no transform events)
32  * 6446941 java.lang.instrument: multiple agent attach fails (first agent chooses capabilities)
33  */
34 import java.net.Socket;
35 import java.net.InetSocketAddress;
36 import java.io.IOException;
37 import java.util.Arrays;
38 import java.security.ProtectionDomain;
39 import java.lang.instrument.ClassFileTransformer;
40 import java.lang.instrument.Instrumentation;
41 import java.lang.instrument.ClassDefinition;
42 
43 public class RedefineAgent implements ClassFileTransformer {
44 
45     static byte[] classfilebytes;
46     static final String targetName = "RedefineDummy";
47     static final String targetNameSlashes = "RedefineDummy";
48     static boolean gotRedefineTransform = false;
49 
50     // test transform and capture class bytes for redefine
transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)51     public byte[] transform(ClassLoader loader,
52                             String className,
53                             Class<?> classBeingRedefined,
54                             ProtectionDomain  protectionDomain,
55                             byte[] classfileBuffer) {
56         if (className.equals(targetNameSlashes)) {
57             if (classBeingRedefined == null) {
58                 System.out.println("Got bytes for: " + className);
59                 classfilebytes = Arrays.copyOf(classfileBuffer, classfileBuffer.length);
60             } else {
61                 gotRedefineTransform = true;
62             }
63         }
64         return null;
65     }
66 
67     // test transform and redefine for an attached agent
testRedefine(Instrumentation inst)68     public static void testRedefine(Instrumentation inst) throws Exception {
69         Class[] classes = inst.getAllLoadedClasses();
70         for (Class k : classes) {
71             if (k.getName().equals(targetName)) {
72                 throw new Exception("RedefineAgent Test error: class " + targetName + " has already been loaded.");
73             }
74         }
75         inst.addTransformer(new RedefineAgent());
76         ClassLoader.getSystemClassLoader().loadClass(targetName);
77         classes = inst.getAllLoadedClasses();
78         Class targetClass = null;
79         for (Class k : classes) {
80             if (k.getName().equals(targetName)) {
81                 targetClass = k;
82                 break;
83             }
84         }
85         if (targetClass == null) {
86             throw new Exception("RedefineAgent Test error: class " + targetName + " not loaded.");
87         }
88         if (classfilebytes == null) {
89             throw new Exception("RedefineAgent Error(6439234): no transform call for class " + targetName);
90         }
91         ClassDefinition cd = new ClassDefinition(targetClass, classfilebytes);
92         inst.redefineClasses(cd);
93         System.out.println("RedefineAgent did redefine.");
94         if (gotRedefineTransform) {
95             System.out.println("RedefineAgent got redefine transform.");
96         } else {
97             throw new Exception("RedefineAgent Error(6439234): no transform call for redefine " + targetName);
98         }
99     }
100 
agentmain(String args, Instrumentation inst)101     public static void agentmain(String args, Instrumentation inst) throws Exception {
102         System.out.println("RedefineAgent running...");
103         System.out.println("RedefineAgent redefine supported: " + inst.isRedefineClassesSupported());
104         int port = Integer.parseInt(args);
105         System.out.println("RedefineAgent connecting back to Tool....");
106         Socket s = new Socket();
107         s.connect( new InetSocketAddress(port) );
108         System.out.println("RedefineAgent connected to Tool.");
109 
110         testRedefine(inst);
111 
112         s.close();
113     }
114 
115 }
116