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 6263319 27 * @requires ((vm.opt.StartFlightRecording == null) | (vm.opt.StartFlightRecording == false)) & ((vm.opt.FlightRecorder == null) | (vm.opt.FlightRecorder == false)) 28 * @summary test setNativeMethodPrefix 29 * @author Robert Field, Sun Microsystems 30 * 31 * @modules java.base/jdk.internal.org.objectweb.asm 32 * java.management 33 * java.instrument 34 * @run shell/timeout=240 MakeJAR2.sh NativeMethodPrefixAgent NativeMethodPrefixApp 'Can-Retransform-Classes: true' 'Can-Set-Native-Method-Prefix: true' 35 * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-CheckIntrinsics -javaagent:NativeMethodPrefixAgent.jar NativeMethodPrefixApp 36 */ 37 38 import java.lang.instrument.*; 39 import java.security.ProtectionDomain; 40 import java.io.*; 41 42 import asmlib.*; 43 44 class NativeMethodPrefixAgent { 45 46 static ClassFileTransformer t0, t1, t2; 47 static Instrumentation inst; 48 49 static class Tr implements ClassFileTransformer { 50 final String trname; 51 final int transformId; 52 53 Tr(int transformId) { 54 this.trname = "tr" + transformId; 55 this.transformId = transformId; 56 } 57 58 public byte[] 59 transform( 60 ClassLoader loader, 61 String className, 62 Class<?> classBeingRedefined, 63 ProtectionDomain protectionDomain, 64 byte[] classfileBuffer) { 65 boolean redef = classBeingRedefined != null; 66 System.out.println(trname + ": " + 67 (redef? "Retransforming " : "Loading ") + className); 68 if (className != null) { 69 try { 70 byte[] newcf = Instrumentor.instrFor(classfileBuffer) 71 .addNativeMethodTrackingInjection( 72 "wrapped_" + trname + "_", 73 (h)->{ 74 h.push(h.getName()); 75 h.push(transformId); 76 h.invokeStatic("bootreporter/StringIdCallbackReporter", "tracker", "(Ljava/lang/String;I)V", false); 77 }) 78 .apply(); 79 /*** debugging ... 80 if (newcf != null) { 81 String fname = trname + (redef?"_redef" : "") + "/" + className; 82 System.err.println("dumping to: " + fname); 83 write_buffer(fname + "_before.class", classfileBuffer); 84 write_buffer(fname + "_instr.class", newcf); 85 } 86 ***/ 87 88 return redef? null : newcf; 89 } catch (Throwable ex) { 90 System.err.println("ERROR: Injection failure: " + ex); 91 ex.printStackTrace(); 92 System.err.println("Returning bad class file, to cause test failure"); 93 return new byte[0]; 94 } 95 } 96 return null; 97 } 98 99 } 100 101 // for debugging 102 static void write_buffer(String fname, byte[]buffer) { 103 try { 104 File f = new File(fname); 105 if (!f.getParentFile().exists()) { 106 f.getParentFile().mkdirs(); 107 } 108 try (FileOutputStream outStream = new FileOutputStream(f)) { 109 outStream.write(buffer, 0, buffer.length); 110 } 111 } catch (IOException ex) { 112 System.err.println("EXCEPTION in write_buffer: " + ex); 113 } 114 } 115 116 public static void 117 premain (String agentArgs, Instrumentation instArg) 118 throws IOException, IllegalClassFormatException, 119 ClassNotFoundException, UnmodifiableClassException { 120 inst = instArg; 121 System.out.println("Premain"); 122 123 t1 = new Tr(1); 124 t2 = new Tr(2); 125 t0 = new Tr(0); 126 inst.addTransformer(t1, true); 127 inst.addTransformer(t2, false); 128 inst.addTransformer(t0, true); 129 instArg.setNativeMethodPrefix(t0, "wrapped_tr0_"); 130 instArg.setNativeMethodPrefix(t1, "wrapped_tr1_"); 131 instArg.setNativeMethodPrefix(t2, "wrapped_tr2_"); 132 133 // warm up: cause load of transformer classes before used during class load 134 instArg.retransformClasses(Runtime.class); 135 } 136 }