OpenJDK / jdk / jdk12
changeset 26205:c073791a67de
8037082: java/lang/instrument/NativeMethodPrefixAgent.java failing
Reviewed-by: sla
author | jbachorik |
---|---|
date | Mon, 25 Aug 2014 18:17:24 +0200 |
parents | 77df35747ce7 |
children | fb87c4051d65 |
files | jdk/test/ProblemList.txt jdk/test/java/lang/instrument/MakeJAR2.sh jdk/test/java/lang/instrument/NativeMethodPrefixAgent.java jdk/test/java/lang/instrument/RetransformAgent.java jdk/test/java/lang/instrument/asmlib/Instrumentor.java jdk/test/java/lang/instrument/ilib/ClassDump.java jdk/test/java/lang/instrument/ilib/ClassReaderWriter.java jdk/test/java/lang/instrument/ilib/Info.java jdk/test/java/lang/instrument/ilib/Inject.java jdk/test/java/lang/instrument/ilib/InjectBytecodes.java jdk/test/java/lang/instrument/ilib/Injector.java jdk/test/java/lang/instrument/ilib/Options.java jdk/test/java/lang/instrument/ilib/RuntimeConstants.java |
diffstat | 13 files changed, 253 insertions(+), 2929 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/test/ProblemList.txt Tue Aug 26 16:42:31 2014 +0800 +++ b/jdk/test/ProblemList.txt Mon Aug 25 18:17:24 2014 +0200 @@ -274,9 +274,6 @@ # jdk_instrument -# 8037082 -java/lang/instrument/NativeMethodPrefixAgent.java generic-all - ############################################################################ # svc_tools
--- a/jdk/test/java/lang/instrument/MakeJAR2.sh Tue Aug 26 16:42:31 2014 +0800 +++ b/jdk/test/java/lang/instrument/MakeJAR2.sh Mon Aug 25 18:17:24 2014 +0200 @@ -75,9 +75,9 @@ cp ${TESTSRC}/${AGENT}.java . cp ${TESTSRC}/${APP}.java . -rm -rf ilib -mkdir ilib -cp ${TESTSRC}/ilib/*.java ilib +rm -rf asmlib +mkdir asmlib +cp ${TESTSRC}/asmlib/*.java asmlib rm -rf bootpath mkdir -p bootpath/bootreporter cp ${TESTSRC}/bootreporter/*.java bootpath/bootreporter @@ -86,7 +86,7 @@ ${JAVAC} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} bootreporter/*.java cd .. -${JAVAC} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${AGENT}.java ilib/*.java +${JAVAC} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -XDignore.symbol.file ${AGENT}.java asmlib/*.java ${JAVAC} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -classpath .${PATHSEP}bootpath ${APP}.java echo "Manifest-Version: 1.0" > ${AGENT}.mf @@ -98,6 +98,6 @@ shift done -${JAR} ${TESTTOOLVMOPTS} cvfm ${AGENT}.jar ${AGENT}.mf ${AGENT}*.class ilib/*.class +${JAR} ${TESTTOOLVMOPTS} cvfm ${AGENT}.jar ${AGENT}.mf ${AGENT}*.class asmlib/*.class -# rm -rf ${AGENT}.java ilib ${AGENT}.mf ${AGENT}*.class +# rm -rf ${AGENT}.java asmlib ${AGENT}.mf ${AGENT}*.class
--- a/jdk/test/java/lang/instrument/NativeMethodPrefixAgent.java Tue Aug 26 16:42:31 2014 +0800 +++ b/jdk/test/java/lang/instrument/NativeMethodPrefixAgent.java Mon Aug 25 18:17:24 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. 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 @@ -35,7 +35,7 @@ import java.security.ProtectionDomain; import java.io.*; -import ilib.*; +import asmlib.*; class NativeMethodPrefixAgent { @@ -62,14 +62,25 @@ System.out.println(trname + ": " + (redef? "Retransforming " : "Loading ") + className); if (className != null) { - Options opt = new Options(); - opt.shouldInstrumentNativeMethods = true; - opt.trackerClassName = "bootreporter/StringIdCallbackReporter"; - opt.wrappedTrackerMethodName = "tracker"; - opt.fixedIndex = transformId; - opt.wrappedPrefix = "wrapped_" + trname + "_"; try { - byte[] newcf = Inject.instrumentation(opt, loader, className, classfileBuffer); + byte[] newcf = Instrumentor.instrFor(classfileBuffer) + .addNativeMethodTrackingInjection( + "wrapped_" + trname + "_", + (h)->{ + h.push(h.getName()); + h.push(transformId); + h.invokeStatic("bootreporter/StringIdCallbackReporter", "tracker", "(Ljava/lang/String;I)V", false); + }) + .apply(); + /*** debugging ... + if (newcf != null) { + String fname = trname + (redef?"_redef" : "") + "/" + className; + System.err.println("dumping to: " + fname); + write_buffer(fname + "_before.class", classfileBuffer); + write_buffer(fname + "_instr.class", newcf); + } + ***/ + return redef? null : newcf; } catch (Throwable ex) { System.err.println("ERROR: Injection failure: " + ex); @@ -86,10 +97,14 @@ // for debugging 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) { + File f = new File(fname); + if (!f.getParentFile().exists()) { + f.getParentFile().mkdirs(); + } + try (FileOutputStream outStream = new FileOutputStream(f)) { + outStream.write(buffer, 0, buffer.length); + } + } catch (IOException ex) { System.err.println("EXCEPTION in write_buffer: " + ex); } }
--- a/jdk/test/java/lang/instrument/RetransformAgent.java Tue Aug 26 16:42:31 2014 +0800 +++ b/jdk/test/java/lang/instrument/RetransformAgent.java Mon Aug 25 18:17:24 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. 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 @@ -34,8 +34,7 @@ import java.lang.instrument.*; import java.security.ProtectionDomain; import java.io.*; - -import ilib.*; +import asmlib.*; class RetransformAgent { @@ -75,20 +74,25 @@ // 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"; + int fixedIndex = redef ? redefIndex : loadIndex; try { - byte[] newcf = Inject.instrumentation(opt, loader, className, classfileBuffer); + byte[] newcf = Instrumentor.instrFor(classfileBuffer) + .addMethodEntryInjection( + nname, + (h)->{ + h.push(fixedIndex); + h.invokeStatic("RetransformAgent", "callTracker", "(I)V", false); + }) + .apply(); /*** debugging ... - String fname = trname + (redef?"_redef" : ""); - write_buffer(fname + "_before.class", classfileBuffer); - write_buffer(fname + "_instr.class", newcf); + if (newcf != null) { + String fname = trname + (redef?"_redef" : "") + "/" + className; + System.err.println("dumping to: " + fname); + write_buffer(fname + "_before.class", classfileBuffer); + write_buffer(fname + "_instr.class", newcf); + } ***/ - System.err.println(trname + ": " + className + " index: " + opt.fixedIndex + + System.err.println(trname + ": " + className + " index: " + fixedIndex + (redef? " REDEF" : " LOAD") + " len before: " + classfileBuffer.length + " after: " + newcf.length); @@ -104,10 +108,14 @@ 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) { + File f = new File(fname); + if (!f.getParentFile().exists()) { + f.getParentFile().mkdirs(); + } + try (FileOutputStream outStream = new FileOutputStream(f)) { + outStream.write(buffer, 0, buffer.length); + } + } catch (IOException ex) { System.err.println("EXCEPTION in write_buffer: " + ex); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/instrument/asmlib/Instrumentor.java Mon Aug 25 18:17:24 2014 +0200 @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package asmlib; + +import java.io.PrintStream; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import jdk.internal.org.objectweb.asm.ClassReader; +import jdk.internal.org.objectweb.asm.ClassVisitor; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; + +import java.util.function.Consumer; +import jdk.internal.org.objectweb.asm.Type; + +public class Instrumentor { + public static class InstrHelper { + private final MethodVisitor mv; + private final String name; + + InstrHelper(MethodVisitor mv, String name) { + this.mv = mv; + this.name = name; + } + + public String getName() { + return this.name; + } + + public void invokeStatic(String owner, String name, String desc, boolean itf) { + mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, itf); + } + + public void invokeSpecial(String owner, String name, String desc) { + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, false); + } + + public void invokeVirtual(String owner, String name, String desc) { + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, false); + } + + public void push(int val) { + if (val >= -1 && val <= 5) { + mv.visitInsn(Opcodes.ICONST_0 + val); + } else if (val >= Byte.MIN_VALUE && val <= Byte.MAX_VALUE) { + mv.visitIntInsn(Opcodes.BIPUSH, val); + } else if (val >= Short.MIN_VALUE && val <= Short.MAX_VALUE) { + mv.visitIntInsn(Opcodes.SIPUSH, val); + } else { + mv.visitLdcInsn(val); + } + } + + public void push(Object val) { + mv.visitLdcInsn(val); + } + + public void println(String s) { + mv.visitFieldInsn(Opcodes.GETSTATIC, Type.getInternalName(System.class), "out", Type.getDescriptor(PrintStream.class)); + mv.visitLdcInsn(s); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(PrintStream.class), "println", Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class)), false); + } + } + + public static Instrumentor instrFor(byte[] classData) { + return new Instrumentor(classData); + } + + + private final ClassReader cr; + private final ClassWriter output; + private ClassVisitor instrumentingVisitor = null; + private final AtomicInteger matches = new AtomicInteger(0); + + private Instrumentor(byte[] classData) { + cr = new ClassReader(classData); + output = new ClassWriter(ClassWriter.COMPUTE_MAXS); + instrumentingVisitor = output; + } + + public synchronized Instrumentor addMethodEntryInjection(String methodName, Consumer<InstrHelper> injector) { + instrumentingVisitor = new ClassVisitor(Opcodes.ASM5, instrumentingVisitor) { + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); + + if (name.equals(methodName)) { + matches.getAndIncrement(); + + mv = new MethodVisitor(Opcodes.ASM5, mv) { + @Override + public void visitCode() { + injector.accept(new InstrHelper(mv, name)); + } + }; + } + return mv; + } + }; + return this; + } + + public synchronized Instrumentor addNativeMethodTrackingInjection(String prefix, Consumer<InstrHelper> injector) { + instrumentingVisitor = new ClassVisitor(Opcodes.ASM5, instrumentingVisitor) { + private final Set<Consumer<ClassVisitor>> wmGenerators = new HashSet<>(); + private String className; + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + this.className = name; + super.visit(version, access, name, signature, superName, interfaces); + } + + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + if ((access & Opcodes.ACC_NATIVE) != 0) { + matches.getAndIncrement(); + + String newName = prefix + name; + wmGenerators.add((v)->{ + MethodVisitor mv = v.visitMethod(access & ~Opcodes.ACC_NATIVE, name, desc, signature, exceptions); + mv.visitCode(); + injector.accept(new InstrHelper(mv, name)); + Type[] argTypes = Type.getArgumentTypes(desc); + Type retType = Type.getReturnType(desc); + + boolean isStatic = (access & Opcodes.ACC_STATIC) != 0; + if (!isStatic) { + mv.visitIntInsn(Opcodes.ALOAD, 0); // load "this" + } + + // load the method parameters + if (argTypes.length > 0) { + int ptr = isStatic ? 0 : 1; + for(Type argType : argTypes) { + mv.visitIntInsn(argType.getOpcode(Opcodes.ILOAD), ptr); + ptr += argType.getSize(); + } + } + + mv.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : Opcodes.INVOKESPECIAL, className, newName, desc, false); + mv.visitInsn(retType.getOpcode(Opcodes.IRETURN)); + + mv.visitMaxs(1, 1); // dummy call; let ClassWriter to deal with this + mv.visitEnd(); + }); + return super.visitMethod(access, newName, desc, signature, exceptions); + } + return super.visitMethod(access, name, desc, signature, exceptions); + } + + @Override + public void visitEnd() { + wmGenerators.stream().forEach((e) -> { + e.accept(cv); + }); + super.visitEnd(); + } + }; + + return this; + } + + public synchronized byte[] apply() { + cr.accept(instrumentingVisitor, ClassReader.SKIP_DEBUG + ClassReader.EXPAND_FRAMES); + + return matches.get() == 0 ? null : output.toByteArray(); + } +}
--- a/jdk/test/java/lang/instrument/ilib/ClassDump.java Tue Aug 26 16:42:31 2014 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,273 +0,0 @@ -/* - * Copyright (c) 2005, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package ilib; - -import java.io.IOException; -import java.io.File; -import java.io.FileOutputStream; -import java.io.DataOutputStream; -import java.io.PrintStream; -import java.io.PrintWriter; -import java.io.CharArrayWriter; -import java.util.List; -import java.util.Iterator; -import java.util.ArrayList; - -public class ClassDump implements RuntimeConstants { - - public static void dump(Options opt, - ClassLoader loader, - String className, - byte[] classfileBuffer) { - ClassReaderWriter c = new ClassReaderWriter(classfileBuffer); - (new ClassDump(className, c)).doit(); - } - - static boolean verbose = true; - - final String className; - final ClassReaderWriter c; - private final PrintStream output; - - int constantPoolCount; - int methodsCount; - - ClassDump(String className, ClassReaderWriter c) { - this.className = className; - this.c = c; - this.output = System.err; - } - - void doit() { - int i; - c.copy(4 + 2 + 2); // magic min/maj version - constantPoolCount = c.copyU2(); - // copy old constant pool - c.copyConstantPool(constantPoolCount); - - traceln("ConstantPool size: " + constantPoolCount); - - c.copy(2 + 2 + 2); // access, this, super - int interfaceCount = c.copyU2(); - traceln("interfaceCount: " + interfaceCount); - c.copy(interfaceCount * 2); - copyFields(); // fields - copyMethods(); // methods - int attrCount = c.copyU2(); - traceln("class attrCount: " + attrCount); - // copy the class attributes - copyAttrs(attrCount); - } - - - void copyFields() { - int count = c.copyU2(); - if (verbose) { - System.out.println("fields count: " + count); - } - for (int i = 0; i < count; ++i) { - c.copy(6); // access, name, descriptor - int attrCount = c.copyU2(); - if (verbose) { - System.out.println("field attr count: " + attrCount); - } - copyAttrs(attrCount); - } - } - - void copyMethods() { - methodsCount = c.copyU2(); - if (verbose) { - System.out.println("methods count: " + methodsCount); - } - for (int i = 0; i < methodsCount; ++i) { - copyMethod(); - } - } - - void copyMethod() { - int accessFlags = c.copyU2();// access flags - int nameIndex = c.copyU2(); // name - checkIndex(nameIndex, "Method name"); - String methodName = c.constantPoolString(nameIndex); - traceln("method: " + methodName); - int descriptorIndex = c.copyU2(); // descriptor - checkIndex(descriptorIndex, "Method descriptor"); - int attrCount = c.copyU2(); // attribute count - if (verbose) { - System.out.println("method attr count: " + attrCount); - } - for (int i = 0; i < attrCount; ++i) { - copyAttrForMethod(methodName, accessFlags); - } - } - - void copyAttrs(int attrCount) { - for (int i = 0; i < attrCount; ++i) { - copyAttr(); - } - } - - void copyAttr() { - c.copy(2); // name - int len = c.copyU4(); // attr len - if (verbose) { - System.out.println("attr len: " + len); - } - c.copy(len); // attribute info - } - - void copyAttrForMethod(String methodName, int accessFlags) { - int nameIndex = c.copyU2(); // name - // check for Code attr - checkIndex(nameIndex, "Method attr name"); - if (nameIndex == c.codeAttributeIndex) { - try { - copyCodeAttr(methodName); - } catch (IOException exc) { - System.err.println("Code Exception - " + exc); - System.exit(1); - } - } else { - int len = c.copyU4(); // attr len - traceln("method attr len: " + len); - c.copy(len); // attribute info - } - } - - void copyAttrForCode() throws IOException { - int nameIndex = c.copyU2(); // name - - checkIndex(nameIndex, "Code attr name"); - int len = c.copyU4(); // attr len - traceln("code attr len: " + len); - c.copy(len); // attribute info - } - - void copyCodeAttr(String methodName) throws IOException { - traceln("Code attr found"); - int attrLength = c.copyU4(); // attr len - checkLength(attrLength, "Code attr length"); - int maxStack = c.readU2(); // max stack - c.copyU2(); // max locals - int codeLength = c.copyU4(); // code length - checkLength(codeLength, "Code length"); - - copyExceptionTable(); - - int attrCount = c.copyU2(); - checkLength(attrCount, "Code attr count"); - for (int i = 0; i < attrCount; ++i) { - copyAttrForCode(); - } - } - - /** - * Copy the exception table for this method code - */ - void copyExceptionTable() throws IOException { - int tableLength = c.copyU2(); // exception table len - checkLength(tableLength, "Exception Table length"); - if (tableLength > 0) { - traceln(); - traceln("Exception table:"); - traceln(" from:old/new to:old/new target:old/new type"); - for (int tcnt = tableLength; tcnt > 0; --tcnt) { - int startPC = c.readU2(); - int endPC = c.readU2(); - int handlerPC = c.readU2(); - int catchType = c.copyU2(); - if (verbose) { - traceFixedWidthInt(startPC, 6); - traceFixedWidthInt(endPC, 6); - traceFixedWidthInt(handlerPC, 6); - trace(" "); - if (catchType == 0) - traceln("any"); - else { - traceln("" + catchType); - } - } - } - } - } - - private void checkIndex(int index, String comment) { - if (index > constantPoolCount) { - output.println("ERROR BAD INDEX " + comment + " : " + index); - } else { - traceln(comment + " : " + index); - } - } - - private void checkLength(int length, String comment) { - if (length > c.inputBytes().length) { - output.println("ERROR BAD LENGTH " + comment + " : " + length); - } else { - traceln(comment + " : " + length); - } - } - - private void trace(String str) { - if (verbose) { - output.print(str); - } - } - - private void traceln(String str) { - if (verbose) { - output.println(str); - } - } - - private void traceln() { - if (verbose) { - output.println(); - } - } - - private void trace(int i) { - if (verbose) { - output.print(i); - } - } - - /** - * Print an integer so that it takes 'length' characters in - * the output. Temporary until formatting code is stable. - */ - private void traceFixedWidthInt(int x, int length) { - if (verbose) { - CharArrayWriter baStream = new CharArrayWriter(); - PrintWriter pStream = new PrintWriter(baStream); - pStream.print(x); - String str = baStream.toString(); - for (int cnt = length - str.length(); cnt > 0; --cnt) - trace(" "); - trace(str); - } - } - - -}
--- a/jdk/test/java/lang/instrument/ilib/ClassReaderWriter.java Tue Aug 26 16:42:31 2014 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,263 +0,0 @@ -/* - * Copyright (c) 2005, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package ilib; - -class ClassReaderWriter implements RuntimeConstants { - - int codeAttributeIndex; - int lineNumberAttributeIndex; - int localVarAttributeIndex; - - private final byte[] orig; - private final byte[] gen; - private final int sectionLength; - - private static final int GROWTH_FACTOR = 2; - private static final int SECTIONS = 2; - private static final String codeAttributeName = "Code"; - private static final String lineNumberAttributeName = "LineNumberTable"; - private static final String localVarAttributeName = "LocalVariableTable"; - - private int[] genSectionPos = new int[SECTIONS]; - - private int inputPos = 0; - private int genPos = 0; - private int markPos = 0; - private int currentSection = 0; - - private String[] constantPool; - - ClassReaderWriter(byte[] orig) { - this.orig = orig; - sectionLength = orig.length * GROWTH_FACTOR; - gen = new byte[sectionLength * SECTIONS]; - for (int section = 0; section < SECTIONS; ++section) { - genSectionPos[section] = section * sectionLength; - } - } - - int setSection(int section) { - int prevSection = currentSection; - genSectionPos[prevSection] = genPos; - genPos = genSectionPos[section]; - currentSection = section; - return prevSection; - } - - byte[] result() { - int section; - int totalLength = 0; - - setSection(0); // save current section - - for (section = 0; section < SECTIONS; ++section) { - int sectionStart = section * sectionLength; - int sectionGenLength = genSectionPos[section] - sectionStart; - totalLength += sectionGenLength; - } - - byte[] newcf = new byte[totalLength]; - int written = 0; - for (section = 0; section < SECTIONS; ++section) { - int sectionStart = section * sectionLength; - int sectionGenLength = genSectionPos[section] - sectionStart; - System.arraycopy(gen, sectionStart, newcf, written, sectionGenLength); - written += sectionGenLength; - } - - return newcf; - } - - int readU1() { - return ((int)orig[inputPos++]) & 0xFF; - } - - int readU2() { - int res = readU1(); - return (res << 8) + readU1(); - } - - short readS2() { - int res = readU1(); - return (short)((res << 8) + readU1()); - } - - int readU4() { - int res = readU2(); - return (res << 16) + readU2(); - } - - void writeU1(int val) { - gen[genPos++] = (byte)val; - } - - void writeU2(int val) { - writeU1(val >> 8); - writeU1(val & 0xFF); - } - - void writeU4(int val) { - writeU2(val >> 16); - writeU2(val & 0xFFFF); - } - - int copyU1() { - int value = readU1(); - writeU1(value); - return value; - } - - int copyU2() { - int value = readU2(); - writeU2(value); - return value; - } - - int copyU4() { - int value = readU4(); - writeU4(value); - return value; - } - - void copy(int count) { - for (int i = 0; i < count; ++i) { - gen[genPos++] = orig[inputPos++]; - } - } - - void skip(int count) { - inputPos += count; - } - - byte[] readBytes(int count) { - byte[] bytes = new byte[count]; - for (int i = 0; i < count; ++i) { - bytes[i] = orig[inputPos++]; - } - return bytes; - } - - void writeBytes(byte[] bytes) { - for (int i = 0; i < bytes.length; ++i) { - gen[genPos++] = bytes[i]; - } - } - - byte[] inputBytes() { - return orig; - } - - int inputPosition() { - return inputPos; - } - - void setInputPosition(int pos) { - inputPos = pos; - } - - void markLocalPositionStart() { - markPos = inputPos; - } - - int localPosition() { - return inputPos - markPos; - } - - void rewind() { - setInputPosition(markPos); - } - - int generatedPosition() { - return genPos; - } - - void randomAccessWriteU2(int pos, int val) { - int savePos = genPos; - genPos = pos; - writeU2(val); - genPos = savePos; - } - - void randomAccessWriteU4(int pos, int val) { - int savePos = genPos; - genPos = pos; - writeU4(val); - genPos = savePos; - } - - String constantPoolString(int index) { - return constantPool[index]; - } - - void copyConstantPool(int constantPoolCount){ - // copy const pool - constantPool = new String[constantPoolCount]; - // index zero not in class file - for (int i = 1; i < constantPoolCount; ++i) { - int tag = readU1(); - writeU1(tag); - switch (tag) { - case CONSTANT_CLASS: - case CONSTANT_STRING: - copy(2); - break; - case CONSTANT_FIELD: - case CONSTANT_METHOD: - case CONSTANT_INTERFACEMETHOD: - case CONSTANT_INTEGER: - case CONSTANT_FLOAT: - case CONSTANT_NAMEANDTYPE: - copy(4); - break; - case CONSTANT_LONG: - case CONSTANT_DOUBLE: - copy(8); - ++i; // these take two CP entries - duh! - break; - case CONSTANT_UTF8: - int len = copyU2(); - byte[] utf8 = readBytes(len); - String str = null; // null to shut the compiler up - try { - str = new String(utf8, "UTF-8"); - } catch (Exception exc) { - throw new Error("CP exception: " + exc); - } - constantPool[i] = str; - if (str.equals(codeAttributeName)) { - codeAttributeIndex = i; - } else if (str.equals(lineNumberAttributeName)) { - lineNumberAttributeIndex = i; - } else if (str.equals(localVarAttributeName)) { - localVarAttributeIndex = i; - } - writeBytes(utf8); - break; - default: - throw new Error(i + " unexpected CP tag: " + tag); - } - } - } - -}
--- a/jdk/test/java/lang/instrument/ilib/Info.java Tue Aug 26 16:42:31 2014 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2005, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package ilib; - -public class Info { - final int counter; - final String className; - final String methodName; - final int location; - - Info(int counter, String className, String methodName, int location) { - this.counter = counter; - this.className = className; - this.methodName = methodName; - this.location = location; - } -}
--- a/jdk/test/java/lang/instrument/ilib/Inject.java Tue Aug 26 16:42:31 2014 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,746 +0,0 @@ -/* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package ilib; - -import java.io.IOException; -import java.io.File; -import java.io.FileOutputStream; -import java.io.DataOutputStream; -import java.util.List; -import java.util.Iterator; -import java.util.ArrayList; - -public class Inject implements RuntimeConstants { - - public static byte[] instrumentation(Options opt, - ClassLoader loader, - String className, - byte[] classfileBuffer) { - ClassReaderWriter c = new ClassReaderWriter(classfileBuffer); - (new Inject(className, c, loader == null, opt)).doit(); - return c.result(); - } - - static boolean verbose = false; - - final String className; - final ClassReaderWriter c; - final boolean isSystem; - final Options options; - - int constantPoolCount; - int methodsCount; - int methodsCountPos; - int profiler; - int wrappedTrackerIndex = 0; - int thisClassIndex = 0; - - TrackerInjector callInjector; - TrackerInjector allocInjector; - TrackerInjector defaultInjector; - - static interface TrackerInjector extends Injector { - void reinit(int tracker); - int stackSize(int currentSize); - } - - static class SimpleInjector implements TrackerInjector { - byte[] injection; - - public int stackSize(int currentSize) { - return currentSize; - } - - public void reinit(int tracker) { - injection = new byte[3]; - injection[0] = (byte)opc_invokestatic; - injection[1] = (byte)(tracker >> 8); - injection[2] = (byte)tracker; - } - - public byte[] bytecodes(String className, String methodName, int location) { - return injection; - } - } - - static class ObjectInjector implements TrackerInjector { - byte[] injection; - - public int stackSize(int currentSize) { - return currentSize + 1; - } - - public void reinit(int tracker) { - injection = new byte[4]; - injection[0] = (byte)opc_dup; - injection[1] = (byte)opc_invokestatic; - injection[2] = (byte)(tracker >> 8); - injection[3] = (byte)tracker; - } - - public byte[] bytecodes(String className, String methodName, int location) { - return injection; - } - } - - class IndexedInjector implements TrackerInjector { - int counter = 0; - int tracker; - List<Info> infoList = new ArrayList<>(); - - public int stackSize(int currentSize) { - return currentSize + 1; - } - - public void reinit(int tracker) { - this.tracker = tracker; - } - - void dump(File outDir, String filename) throws IOException { - try (FileOutputStream fileOut = - new FileOutputStream(new File(outDir, filename)); - DataOutputStream dataOut = new DataOutputStream(fileOut)) - { - String currentClassName = null; - - dataOut.writeInt(infoList.size()); - for (Iterator<Info> it = infoList.iterator(); it.hasNext(); ) { - Info info = it.next(); - if (!info.className.equals(currentClassName)) { - dataOut.writeInt(123456); // class name marker - currentClassName = info.className; - dataOut.writeUTF(currentClassName); - } - dataOut.writeInt(info.location); - dataOut.writeUTF(info.methodName); - } - } - } - - public byte[] bytecodes(String className, String methodName, int location) { - byte[] injection = new byte[6]; - int injectedIndex = options.fixedIndex != 0? options.fixedIndex : ++counter; - infoList.add(new Info(counter, className, methodName, location)); - injection[0] = (byte)opc_sipush; - injection[1] = (byte)(injectedIndex >> 8); - injection[2] = (byte)injectedIndex; - injection[3] = (byte)opc_invokestatic; - injection[4] = (byte)(tracker >> 8); - injection[5] = (byte)tracker; - return injection; - } - } - - Inject(String className, ClassReaderWriter c, boolean isSystem, Options options) { - this.className = className; - this.c = c; - this.isSystem = isSystem; - this.options = options; - } - - void doit() { - int i; - c.copy(4 + 2 + 2); // magic min/maj version - int constantPoolCountPos = c.generatedPosition(); - constantPoolCount = c.copyU2(); - // copy old constant pool - c.copyConstantPool(constantPoolCount); - - if (verbose) { - System.out.println("ConstantPool expanded from: " + - constantPoolCount); - } - - profiler = addClassToConstantPool(options.trackerClassName); - if (options.shouldInstrumentNew || options.shouldInstrumentObjectInit) { - if (options.shouldInstrumentIndexed) { - if (allocInjector == null) { - // first time - create it - allocInjector = new IndexedInjector(); - } - int allocTracker = addMethodToConstantPool(profiler, - options.allocTrackerMethodName, - "(I)V"); - allocInjector.reinit(allocTracker); - } else if (options.shouldInstrumentObject) { - if (allocInjector == null) { - // first time - create it - allocInjector = new ObjectInjector(); - } - int allocTracker = addMethodToConstantPool(profiler, - options.allocTrackerMethodName, - "(Ljava/lang/Object;)V"); - allocInjector.reinit(allocTracker); - } else { - if (allocInjector == null) { - // first time - create it - allocInjector = new SimpleInjector(); - } - int allocTracker = addMethodToConstantPool(profiler, - options.allocTrackerMethodName, - "()V"); - allocInjector.reinit(allocTracker); - } - defaultInjector = allocInjector; - } - if (options.shouldInstrumentCall) { - if (options.shouldInstrumentIndexed) { - if (callInjector == null) { - // first time - create it - callInjector = new IndexedInjector(); - } - int callTracker = addMethodToConstantPool(profiler, - options.callTrackerMethodName, - "(I)V"); - callInjector.reinit(callTracker); - } else { - if (callInjector == null) { - // first time - create it - callInjector = new SimpleInjector(); - } - int callTracker = addMethodToConstantPool(profiler, - options.callTrackerMethodName, - "()V"); - callInjector.reinit(callTracker); - } - defaultInjector = callInjector; - } - - if (verbose) { - System.out.println("To: " + constantPoolCount); - } - - c.setSection(1); - - c.copy(2 + 2 + 2); // access, this, super - int interfaceCount = c.copyU2(); - if (verbose) { - System.out.println("interfaceCount: " + interfaceCount); - } - c.copy(interfaceCount * 2); - copyFields(); // fields - copyMethods(); // methods - int attrCountPos = c.generatedPosition(); - int attrCount = c.copyU2(); - if (verbose) { - System.out.println("class attrCount: " + attrCount); - } - // copy the class attributes - copyAttrs(attrCount); - - c.randomAccessWriteU2(constantPoolCountPos, constantPoolCount); - } - - - void copyFields() { - int count = c.copyU2(); - if (verbose) { - System.out.println("fields count: " + count); - } - for (int i = 0; i < count; ++i) { - c.copy(6); // access, name, descriptor - int attrCount = c.copyU2(); - if (verbose) { - System.out.println("field attr count: " + attrCount); - } - copyAttrs(attrCount); - } - } - - void copyMethods() { - methodsCountPos = c.generatedPosition(); - methodsCount = c.copyU2(); - int initialMethodsCount = methodsCount; - if (verbose) { - System.out.println("methods count: " + methodsCount); - } - for (int i = 0; i < initialMethodsCount; ++i) { - copyMethod(); - } - } - - void copyMethod() { - int accessFlags = c.copyU2();// access flags - if (options.shouldInstrumentNativeMethods && (accessFlags & ACC_NATIVE) != 0) { - wrapNativeMethod(accessFlags); - return; - } - int nameIndex = c.copyU2(); // name - String methodName = c.constantPoolString(nameIndex); - c.copyU2(); // descriptor - int attrCount = c.copyU2(); // attribute count - if (verbose) { - System.out.println("methods attr count: " + attrCount); - } - for (int i = 0; i < attrCount; ++i) { - copyAttrForMethod(methodName, accessFlags); - } - } - - void wrapNativeMethod(int accessFlags) { - // first, copy the native method with the name changed - // accessFlags have already been copied - int nameIndex = c.readU2(); // name - String methodName = c.constantPoolString(nameIndex); - String wrappedMethodName = options.wrappedPrefix + methodName; - int wrappedNameIndex = writeCPEntryUtf8(wrappedMethodName); - c.writeU2(wrappedNameIndex); // change to the wrapped name - - int descriptorIndex = c.copyU2(); // descriptor index - - int attrCount = c.copyU2(); // attribute count - // need to replicate these attributes (esp Exceptions) in wrapper - // so mark this location so we can rewind - c.markLocalPositionStart(); - for (int i = 0; i < attrCount; ++i) { - copyAttrForMethod(methodName, accessFlags); - } - if (true) { - System.err.println(" wrapped: " + methodName); - } - - // now write the wrapper method - c.writeU2(accessFlags & ~ACC_NATIVE); - c.writeU2(nameIndex); // original unwrapped name - c.writeU2(descriptorIndex); // descriptor is the same - - c.writeU2(attrCount + 1); // wrapped plus a code attribute - // rewind to wrapped attributes - c.rewind(); - for (int i = 0; i < attrCount; ++i) { - copyAttrForMethod(methodName, accessFlags); - } - - // generate a Code attribute for the wrapper method - int wrappedIndex = addMethodToConstantPool(getThisClassIndex(), - wrappedNameIndex, - descriptorIndex); - String descriptor = c.constantPoolString(descriptorIndex); - createWrapperCodeAttr(nameIndex, accessFlags, descriptor, wrappedIndex); - - // increment method count - c.randomAccessWriteU2(methodsCountPos, ++methodsCount); - } - - void copyAttrs(int attrCount) { - for (int i = 0; i < attrCount; ++i) { - copyAttr(); - } - } - - void copyAttr() { - c.copy(2); // name - int len = c.copyU4(); // attr len - if (verbose) { - System.out.println("attr len: " + len); - } - c.copy(len); // attribute info - } - - void copyAttrForMethod(String methodName, int accessFlags) { - int nameIndex = c.copyU2(); // name - // check for Code attr - if (nameIndex == c.codeAttributeIndex) { - try { - copyCodeAttr(methodName); - } catch (IOException exc) { - System.err.println("Code Exception - " + exc); - System.exit(1); - } - } else { - int len = c.copyU4(); // attr len - if (verbose) { - System.out.println("method attr len: " + len); - } - c.copy(len); // attribute info - } - } - - void copyAttrForCode(InjectBytecodes ib) throws IOException { - int nameIndex = c.copyU2(); // name - - // check for Code attr - if (nameIndex == c.lineNumberAttributeIndex) { - ib.copyLineNumberAttr(); - } else if (nameIndex == c.localVarAttributeIndex) { - ib.copyLocalVarAttr(); - } else { - int len = c.copyU4(); // attr len - if (verbose) { - System.out.println("code attr len: " + len); - } - c.copy(len); // attribute info - } - } - - void copyCodeAttr(String methodName) throws IOException { - if (verbose) { - System.out.println("Code attr found"); - } - int attrLengthPos = c.generatedPosition(); - int attrLength = c.copyU4(); // attr len - int maxStack = c.readU2(); // max stack - c.writeU2(defaultInjector == null? maxStack : - defaultInjector.stackSize(maxStack)); // big enough for injected code - c.copyU2(); // max locals - int codeLengthPos = c.generatedPosition(); - int codeLength = c.copyU4(); // code length - if (options.targetMethod != null && !options.targetMethod.equals(methodName)) { - c.copy(attrLength - 8); // copy remainder minus already copied - return; - } - if (isSystem) { - if (codeLength == 1 && methodName.equals("finalize")) { - if (verbose) { - System.out.println("empty system finalizer not instrumented"); - } - c.copy(attrLength - 8); // copy remainder minus already copied - return; - } - if (codeLength == 1 && methodName.equals("<init>")) { - if (verbose) { - System.out.println("empty system constructor not instrumented"); - } - if (!options.shouldInstrumentObjectInit) { - c.copy(attrLength - 8); // copy remainder minus already copied - return; - } - } - if (methodName.equals("<clinit>")) { - if (verbose) { - System.out.println("system class initializer not instrumented"); - } - c.copy(attrLength - 8); // copy remainder minus already copied - return; - } - } - if (options.shouldInstrumentObjectInit - && (!className.equals("java/lang/Object") - || !methodName.equals("<init>"))) { - c.copy(attrLength - 8); // copy remainder minus already copied - return; - } - - InjectBytecodes ib = new InjectBytecodes(c, codeLength, className, methodName); - - if (options.shouldInstrumentNew) { - ib.injectAfter(opc_new, allocInjector); - ib.injectAfter(opc_newarray, allocInjector); - ib.injectAfter(opc_anewarray, allocInjector); - ib.injectAfter(opc_multianewarray, allocInjector); - } - if (options.shouldInstrumentCall) { - ib.inject(0, callInjector.bytecodes(className, methodName, 0)); - } - if (options.shouldInstrumentObjectInit) { - ib.inject(0, allocInjector.bytecodes(className, methodName, 0)); - } - - ib.adjustOffsets(); - - // fix up code length - int newCodeLength = c.generatedPosition() - (codeLengthPos + 4); - c.randomAccessWriteU4(codeLengthPos, newCodeLength); - if (verbose) { - System.out.println("code length old: " + codeLength + - ", new: " + newCodeLength); - } - - ib.copyExceptionTable(); - - int attrCount = c.copyU2(); - for (int i = 0; i < attrCount; ++i) { - copyAttrForCode(ib); - } - - // fix up attr length - int newAttrLength = c.generatedPosition() - (attrLengthPos + 4); - c.randomAccessWriteU4(attrLengthPos, newAttrLength); - if (verbose) { - System.out.println("attr length old: " + attrLength + - ", new: " + newAttrLength); - } - } - - int nextDescriptorIndex(String descriptor, int index) { - switch (descriptor.charAt(index)) { - case 'B': // byte - case 'C': // char - case 'I': // int - case 'S': // short - case 'Z': // boolean - case 'F': // float - case 'D': // double - case 'J': // long - return index + 1; - case 'L': // object - int i = index + 1; - while (descriptor.charAt(i) != ';') { - ++i; - } - return i + 1; - case '[': // array - return nextDescriptorIndex(descriptor, index + 1); - } - throw new InternalError("should not reach here"); - } - - int getWrappedTrackerIndex() { - if (wrappedTrackerIndex == 0) { - wrappedTrackerIndex = addMethodToConstantPool(profiler, - options.wrappedTrackerMethodName, - "(Ljava/lang/String;I)V"); - } - return wrappedTrackerIndex; - } - - int getThisClassIndex() { - if (thisClassIndex == 0) { - thisClassIndex = addClassToConstantPool(className); - } - return thisClassIndex; - } - - int computeMaxLocals(String descriptor, int accessFlags) { - int index = 1; - int slot = 0; - - if ((accessFlags & ACC_STATIC) == 0) { - ++slot; - } - char type; - while ((type = descriptor.charAt(index)) != ')') { - switch (type) { - case 'B': // byte - case 'C': // char - case 'I': // int - case 'S': // short - case 'Z': // boolean - case 'F': // float - case 'L': // object - case '[': // array - ++slot; - break; - case 'D': // double - case 'J': // long - slot += 2; - break; - } - index = nextDescriptorIndex(descriptor, index); - } - - return slot; - } - - - void createWrapperCodeAttr(int methodNameIndex, int accessFlags, - String descriptor, int wrappedIndex) { - int maxLocals = computeMaxLocals(descriptor, accessFlags); - - c.writeU2(c.codeAttributeIndex); // - int attrLengthPos = c.generatedPosition(); - c.writeU4(0); // attr len -- fix up below - c.writeU2(maxLocals + 4); // max stack - c.writeU2(maxLocals); // max locals - int codeLengthPos = c.generatedPosition(); - c.writeU4(0); // code length -- fix up below - - int methodStringIndex = writeCPEntryString(methodNameIndex); - - c.writeU1(opc_ldc_w); - c.writeU2(methodStringIndex); // send the method name - c.writeU1(opc_sipush); - c.writeU2(options.fixedIndex); - c.writeU1(opc_invokestatic); - c.writeU2(getWrappedTrackerIndex()); - - // set-up args - int index = 1; - int slot = 0; - if ((accessFlags & ACC_STATIC) == 0) { - c.writeU1(opc_aload_0); // this - ++slot; - } - char type; - while ((type = descriptor.charAt(index)) != ')') { - switch (type) { - case 'B': // byte - case 'C': // char - case 'I': // int - case 'S': // short - case 'Z': // boolean - c.writeU1(opc_iload); - c.writeU1(slot); - ++slot; - break; - case 'F': // float - c.writeU1(opc_fload); - c.writeU1(slot); - ++slot; - break; - case 'D': // double - c.writeU1(opc_dload); - c.writeU1(slot); - slot += 2; - break; - case 'J': // long - c.writeU1(opc_lload); - c.writeU1(slot); - slot += 2; - break; - case 'L': // object - case '[': // array - c.writeU1(opc_aload); - c.writeU1(slot); - ++slot; - break; - } - index = nextDescriptorIndex(descriptor, index); - } - - // call the wrapped version - if ((accessFlags & ACC_STATIC) == 0) { - c.writeU1(opc_invokevirtual); - } else { - c.writeU1(opc_invokestatic); - } - c.writeU2(wrappedIndex); - - // return correct type - switch (descriptor.charAt(index+1)) { - case 'B': // byte - case 'C': // char - case 'I': // int - case 'S': // short - case 'Z': // boolean - c.writeU1(opc_ireturn); - break; - case 'F': // float - c.writeU1(opc_freturn); - break; - case 'D': // double - c.writeU1(opc_dreturn); - break; - case 'J': // long - c.writeU1(opc_lreturn); - break; - case 'L': // object - case '[': // array - c.writeU1(opc_areturn); - break; - case 'V': // void - c.writeU1(opc_return); - break; - } - - // end of code - - // fix up code length - int newCodeLength = c.generatedPosition() - (codeLengthPos + 4); - c.randomAccessWriteU4(codeLengthPos, newCodeLength); - - c.writeU2(0); // exception table length - c.writeU2(0); // attribute count - - // fix up attr length - int newAttrLength = c.generatedPosition() - (attrLengthPos + 4); - c.randomAccessWriteU4(attrLengthPos, newAttrLength); - } - - - int addClassToConstantPool(String className) { - int prevSection = c.setSection(0); - int classNameIndex = writeCPEntryUtf8(className); - int classIndex = writeCPEntryClass(classNameIndex); - c.setSection(prevSection); - return classIndex; - } - - int addMethodToConstantPool(int classIndex, - String methodName, - String descr) { - int prevSection = c.setSection(0); - int methodNameIndex = writeCPEntryUtf8(methodName); - int descrIndex = writeCPEntryUtf8(descr); - c.setSection(prevSection); - return addMethodToConstantPool(classIndex, methodNameIndex, descrIndex); - } - - int addMethodToConstantPool(int classIndex, - int methodNameIndex, - int descrIndex) { - int prevSection = c.setSection(0); - int nameAndTypeIndex = writeCPEntryNameAndType(methodNameIndex, - descrIndex); - int methodIndex = writeCPEntryMethodRef(classIndex, nameAndTypeIndex); - c.setSection(prevSection); - return methodIndex; - } - - int writeCPEntryUtf8(String str) { - int prevSection = c.setSection(0); - int len = str.length(); - c.writeU1(CONSTANT_UTF8); // Utf8 tag - c.writeU2(len); - for (int i = 0; i < len; ++i) { - c.writeU1(str.charAt(i)); - } - c.setSection(prevSection); - return constantPoolCount++; - } - - int writeCPEntryString(int utf8Index) { - int prevSection = c.setSection(0); - c.writeU1(CONSTANT_STRING); - c.writeU2(utf8Index); - c.setSection(prevSection); - return constantPoolCount++; - } - - int writeCPEntryClass(int classNameIndex) { - int prevSection = c.setSection(0); - c.writeU1(CONSTANT_CLASS); - c.writeU2(classNameIndex); - c.setSection(prevSection); - return constantPoolCount++; - } - - int writeCPEntryNameAndType(int nameIndex, int descrIndex) { - int prevSection = c.setSection(0); - c.writeU1(CONSTANT_NAMEANDTYPE); - c.writeU2(nameIndex); - c.writeU2(descrIndex); - c.setSection(prevSection); - return constantPoolCount++; - } - - int writeCPEntryMethodRef(int classIndex, int nameAndTypeIndex) { - int prevSection = c.setSection(0); - c.writeU1(CONSTANT_METHOD); - c.writeU2(classIndex); - c.writeU2(nameAndTypeIndex); - c.setSection(prevSection); - return constantPoolCount++; - } -}
--- a/jdk/test/java/lang/instrument/ilib/InjectBytecodes.java Tue Aug 26 16:42:31 2014 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,769 +0,0 @@ -/* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * An extension of BinaryCode that allows code to be printed. - * Includes printing of disassembled byte codes, exception info, - * local variable and line number info. - * - */ - -package ilib; - -import java.io.ByteArrayInputStream; -import java.io.CharArrayWriter; -import java.io.DataInputStream; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.PrintStream; -import java.util.Map; -import java.util.HashMap; - -class InjectBytecodes implements RuntimeConstants { - - private final ClassReaderWriter c; - private final PrintStream output; - private final int length; - private final int[] map; - private final byte[] widening; - private final Injector[] before = new Injector[256]; - private final Injector[] after = new Injector[256]; - private final String className; - private final String methodName; - private final Map<Integer,byte[]> snippets = new HashMap<>(); - - private int pos; - private int newPos; - - private class Span { - final int delta; - final int target; - final int newDelta; - final int newTarget; - - Span(int delta) { - this.delta = delta; - this.target = pos + delta; - this.newTarget = map[target]; - this.newDelta = newTarget - newPos; - } - } - - /** - * Constructor - */ - InjectBytecodes(ClassReaderWriter c, int length, - String className, String methodName) { - this.c = c; - this.output = System.out; - this.length = length; - this.map = new int[length + 1]; - this.widening = new byte[length + 1]; - this.className = className; - this.methodName = methodName; - c.markLocalPositionStart(); - for (int i = 0; i <= length; ++i) { - map[i] = i; - } - } - - public void inject(int at, byte[] newCode) { - snippets.put(new Integer(at), newCode); - trace("external "); - inject(at, newCode.length); - } - - private void inject(int at, int len) { - if (Inject.verbose) { - traceln("Injecting " + len + " at " + at); - } - for (int i = at; i <= length; ++i) { - map[i] += len; - } - } - - private void widen(int at, int len) { - int delta = len - widening[at]; - if (Inject.verbose) { - traceln(); - traceln("Widening to " + len + " at " + at); - } - inject(c.localPosition(), delta); // inject at end of instruction - widening[at] = (byte)len; // mark at beginning of instruction - } - - public void injectBefore(int code, Injector inj) { - before[code] = inj; - } - - public void injectAfter(int code, Injector inj) { - after[code] = inj; - } - - private void trace(String str) { - if (Inject.verbose) { - output.print(str); - } - } - - private void traceln(String str) { - if (Inject.verbose) { - output.println(str); - } - } - - private void traceln() { - if (Inject.verbose) { - output.println(); - } - } - - private void trace(int i) { - if (Inject.verbose) { - output.print(i); - } - } - - /** - * Print an integer so that it takes 'length' characters in - * the output. Temporary until formatting code is stable. - */ - private void traceFixedWidthInt(int x, int length) { - if (Inject.verbose) { - CharArrayWriter baStream = new CharArrayWriter(); - PrintWriter pStream = new PrintWriter(baStream); - pStream.print(x); - String str = baStream.toString(); - for (int cnt = length - str.length(); cnt > 0; --cnt) - trace(" "); - trace(str); - } - } - - void adjustOffsets() throws IOException { - if (Inject.verbose) { - traceln(); - traceln("Method " + methodName); - traceln(); - } - c.rewind(); - while (c.localPosition() < length) { - insertAtInstruction(); - } - trace("Searching for adjustments..."); - c.rewind(); - while (c.localPosition() < length) { - if (!adjustInstruction()) { - c.rewind(); - traceln(); - traceln("Restarting adjustments after change..."); - } - } - // write the new bytecodes - traceln(); - traceln(); - trace("Writing new code..."); - c.rewind(); - while (c.localPosition() < length) { - writeInstruction(); - } - if (!snippets.isEmpty()) { - throw new Error("not all snippets written"); - } - } - - /** - * Walk one instruction inserting instrumentation at specified instructions - */ - private void insertAtInstruction() throws IOException { - pos = c.localPosition(); - int opcode = c.readU1(); - if (opcode == opc_wide) { - // no support for instrumenting wide instructions - int wopcode = c.readU1(); - int lvIndex = c.readU2(); - switch (wopcode) { - case opc_aload: case opc_astore: - case opc_fload: case opc_fstore: - case opc_iload: case opc_istore: - case opc_lload: case opc_lstore: - case opc_dload: case opc_dstore: - case opc_ret: - break; - - case opc_iinc: - c.readS2(); - break; - default: - throw new Error("Invalid wide opcode: " + wopcode); - } - } else { - Injector inj; - - inj = before[opcode]; - if (inj != null) { - inject(pos, inj.bytecodes(className, methodName, pos)); - } - - switch (opcode) { - case opc_tableswitch:{ - int header = (pos+1+3) & (~3); // 4byte boundry - c.skip(header - (pos+1)); // skip old padding - - c.readU4(); - int low = c.readU4(); - int high = c.readU4(); - c.skip((high+1-low) * 4); - break; - } - - case opc_lookupswitch:{ - int header = (pos+1+3) & (~3); // 4byte boundry - c.skip(header - (pos+1)); // skip padding - - c.readU4(); - int npairs = c.readU4(); - c.skip(npairs * 8); - break; - } - - default: { - int instrLen = opcLengths[opcode]; - c.skip(instrLen-1); - } - } - inj = after[opcode]; - if (inj != null) { - pos = c.localPosition(); - inject(pos, inj.bytecodes(className, methodName, pos)); - } - } - } - - /** - * Walk one instruction adjusting for insertions - */ - private boolean adjustInstruction() throws IOException { - pos = c.localPosition(); - newPos = map[pos]; - int opcode = c.readU1(); - if (Inject.verbose) { - traceln(); - traceFixedWidthInt(pos, 4); - traceFixedWidthInt(newPos, 4); - trace(" "); - } - if (opcode == opc_wide) { - int wopcode = c.readU1(); - int lvIndex = c.readU2(); - if (Inject.verbose) { - trace(opcNames[wopcode] + "_w "); - } - switch (wopcode) { - case opc_aload: case opc_astore: - case opc_fload: case opc_fstore: - case opc_iload: case opc_istore: - case opc_lload: case opc_lstore: - case opc_dload: case opc_dstore: - case opc_ret: - trace(lvIndex); - break; - - case opc_iinc: - int constVal = c.readS2(); - if (Inject.verbose) { - trace(lvIndex + " " + constVal); - } - break; - default: - throw new Error("Invalid wide opcode: " + wopcode); - } - } else { - if (Inject.verbose) { - trace(opcNames[opcode]); - } - switch (opcode) { - - case opc_tableswitch:{ - int widened = widening[pos]; - int header = (pos+1+3) & (~3); // 4byte boundry - int newHeader = (newPos+1+3) & (~3); // 4byte boundry - - c.skip(header - (pos+1)); // skip old padding - - Span defaultSkip = new Span(c.readU4()); - int low = c.readU4(); - int high = c.readU4(); - if (Inject.verbose) { - trace(" " + low + " to " + high); - trace(": default= [was] " + defaultSkip.target); - trace(" [now] " + defaultSkip.newTarget); - for (int i = low; i <= high; ++i) { - Span jump = new Span(c.readU4()); - traceln(""); - trace('\t'); - traceFixedWidthInt(i, 5); - trace(": " + jump.newTarget); - } - } else { - c.skip((high+1-low) * 4); - } - int newPadding = newHeader - newPos; - int oldPadding = header - pos; - int deltaPadding = newPadding - oldPadding; - if (widened != deltaPadding) { - widen(pos, deltaPadding); - return false; // cause restart - } - break; - } - - case opc_lookupswitch:{ - int widened = widening[pos]; - int header = (pos+1+3) & (~3); // 4byte boundry - int newHeader = (newPos+1+3) & (~3); // 4byte boundry - - c.skip(header - (pos+1)); // skip old padding - - Span defaultSkip = new Span(c.readU4()); - int npairs = c.readU4(); - if (Inject.verbose) { - trace(" npairs: " + npairs); - trace(": default= [was] " + defaultSkip.target); - trace(" [now] " + defaultSkip.newTarget); - for (int i = 0; i< npairs; ++i) { - int match = c.readU4(); - Span jump = new Span(c.readU4()); - traceln(""); - trace('\t'); - traceFixedWidthInt(match, 5); - trace(": " + jump.newTarget); - } - } else { - c.skip(npairs * 8); - } - int newPadding = newHeader - newPos; - int oldPadding = header - pos; - int deltaPadding = newPadding - oldPadding; - if (widened != deltaPadding) { - widen(pos, deltaPadding); - return false; // cause restart - } - break; - } - - case opc_jsr: case opc_goto: - case opc_ifeq: case opc_ifge: case opc_ifgt: - case opc_ifle: case opc_iflt: case opc_ifne: - case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpge: - case opc_if_icmpgt: case opc_if_icmple: case opc_if_icmplt: - case opc_if_acmpeq: case opc_if_acmpne: - case opc_ifnull: case opc_ifnonnull: { - int widened = widening[pos]; - Span jump = new Span(c.readS2()); - if (widened == 0) { // not yet widened - int newDelta = jump.newDelta; - if ((newDelta < -32768) || (newDelta > 32767)) { - switch (opcode) { - case opc_jsr: case opc_goto: - widen(pos, 2); // will convert to wide - break; - default: - widen(pos, 5); // will inject goto_w - break; - } - return false; // cause restart - } - } - if (Inject.verbose) { - trace(" [was] " + jump.target + " ==> " + - " [now] " + jump.newTarget); - } - break; - } - - case opc_jsr_w: - case opc_goto_w: { - Span jump = new Span(c.readU4()); - if (Inject.verbose) { - trace(" [was] " + jump.target + - " [now] " + jump.newTarget); - } - break; - } - - default: { - int instrLen = opcLengths[opcode]; - c.skip(instrLen-1); - break; - } - } - } - return true; // successful return - } - - - /** - * Walk one instruction writing the transformed instruction. - */ - private void writeInstruction() throws IOException { - pos = c.localPosition(); - newPos = map[pos]; - byte[] newCode = snippets.remove(new Integer(pos)); - if (newCode != null) { - traceln(); - traceFixedWidthInt(pos, 4); - trace(" ... -- Inserting new code"); - c.writeBytes(newCode); - } - int opcode = c.readU1(); - if (Inject.verbose) { - traceln(); - traceFixedWidthInt(pos, 4); - traceFixedWidthInt(newPos, 4); - trace(" "); - } - if (opcode == opc_wide) { - int wopcode = c.readU1(); - int lvIndex = c.readU2(); - if (Inject.verbose) { - trace(opcNames[wopcode] + "_w "); - } - c.writeU1(opcode); - c.writeU1(wopcode); - c.writeU2(lvIndex); - switch (wopcode) { - case opc_aload: case opc_astore: - case opc_fload: case opc_fstore: - case opc_iload: case opc_istore: - case opc_lload: case opc_lstore: - case opc_dload: case opc_dstore: - case opc_ret: - trace(lvIndex); - break; - - case opc_iinc: - int constVal = c.readS2(); - c.writeU2(constVal); // ??? U vs S - if (Inject.verbose) { - trace(lvIndex + " " + constVal); - } - break; - default: - throw new Error("Invalid wide opcode: " + wopcode); - } - } else { - if (Inject.verbose) { - trace(opcNames[opcode]); - } - switch (opcode) { - - case opc_tableswitch:{ - int header = (pos+1+3) & (~3); // 4byte boundry - int newHeader = (newPos+1+3) & (~3); // 4byte boundry - - c.skip(header - (pos+1)); // skip old padding - - Span defaultSkip = new Span(c.readU4()); - int low = c.readU4(); - int high = c.readU4(); - - c.writeU1(opcode); // copy instruction - for (int i = newPos+1; i < newHeader; ++i) { - c.writeU1(0); // write new padding - } - c.writeU4(defaultSkip.newDelta); - c.writeU4(low); - c.writeU4(high); - - if (Inject.verbose) { - trace(" " + low + " to " + high); - trace(": default= [was] " + defaultSkip.target); - trace(" [now] " + defaultSkip.newTarget); - } - for (int i = low; i <= high; ++i) { - Span jump = new Span(c.readU4()); - c.writeU4(jump.newDelta); - if (Inject.verbose) { - traceln(""); - trace('\t'); - traceFixedWidthInt(i, 5); - trace(": " + jump.newTarget); - } - } - break; - } - - case opc_lookupswitch:{ - int header = (pos+1+3) & (~3); // 4byte boundry - int newHeader = (newPos+1+3) & (~3); // 4byte boundry - - c.skip(header - (pos+1)); // skip old padding - - Span defaultSkip = new Span(c.readU4()); - int npairs = c.readU4(); - if (Inject.verbose) { - trace(" npairs: " + npairs); - trace(": default= [was] " + defaultSkip.target); - trace(" [now] " + defaultSkip.newTarget); - } - c.writeU1(opcode); // copy instruction - for (int i = newPos+1; i < newHeader; ++i) { - c.writeU1(0); // write new padding - } - c.writeU4(defaultSkip.newDelta); - c.writeU4(npairs); - for (int i = 0; i< npairs; ++i) { - int match = c.readU4(); - Span jump = new Span(c.readU4()); - c.writeU4(match); - c.writeU4(jump.newDelta); - if (Inject.verbose) { - traceln(""); - trace('\t'); - traceFixedWidthInt(match, 5); - trace(": " + jump.newTarget); - } - } - break; - } - - case opc_jsr: case opc_goto: - case opc_ifeq: case opc_ifge: case opc_ifgt: - case opc_ifle: case opc_iflt: case opc_ifne: - case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpge: - case opc_if_icmpgt: case opc_if_icmple: case opc_if_icmplt: - case opc_if_acmpeq: case opc_if_acmpne: - case opc_ifnull: case opc_ifnonnull: { - int widened = widening[pos]; - Span jump = new Span(c.readS2()); - int newOpcode = opcode; // default to unchanged - if (widened == 0) { // not widened - c.writeU1(opcode); // rewrite instruction - c.writeU2(jump.newDelta); - } else if (widened == 2) { // wide form - switch (opcode) { - case opc_jsr: - newOpcode = opc_jsr_w; - break; - case opc_goto: - newOpcode = opc_jsr_w; - break; - default: - throw new Error("unexpected opcode: " + - opcode); - } - c.writeU1(newOpcode); // write wide instruction - c.writeU4(jump.newDelta); // write new and wide delta - } else if (widened == 5) { // insert goto_w - switch (opcode) { - case opc_ifeq: - newOpcode = opc_ifne; - break; - case opc_ifge: - newOpcode = opc_iflt; - break; - case opc_ifgt: - newOpcode = opc_ifle; - break; - case opc_ifle: - newOpcode = opc_ifgt; - break; - case opc_iflt: - newOpcode = opc_ifge; - break; - case opc_ifne: - newOpcode = opc_ifeq; - break; - case opc_if_icmpeq: - newOpcode = opc_if_icmpne; - break; - case opc_if_icmpne: - newOpcode = opc_if_icmpeq; - break; - case opc_if_icmpge: - newOpcode = opc_if_icmplt; - break; - case opc_if_icmpgt: - newOpcode = opc_if_icmple; - break; - case opc_if_icmple: - newOpcode = opc_if_icmpgt; - break; - case opc_if_icmplt: - newOpcode = opc_if_icmpge; - break; - case opc_if_acmpeq: - newOpcode = opc_if_acmpne; - break; - case opc_if_acmpne: - newOpcode = opc_if_acmpeq; - break; - case opc_ifnull: - newOpcode = opc_ifnonnull; - break; - case opc_ifnonnull: - newOpcode = opc_ifnull; - break; - default: - throw new Error("unexpected opcode: " + - opcode); - } - c.writeU1(newOpcode); // write inverse branch - c.writeU2(3 + 5); // beyond if and goto_w - c.writeU1(opc_goto_w);// add a goto_w - c.writeU4(jump.newDelta); // write new and wide delta - } else { - throw new Error("unexpected widening"); - } - - if (Inject.verbose) { - trace(" [was] " + jump.target + " ==> " + - opcNames[newOpcode] + - " [now] " + jump.newTarget); - } - break; - } - - case opc_jsr_w: - case opc_goto_w: { - Span jump = new Span(c.readU4()); - c.writeU1(opcode); // instruction itself - c.writeU4(jump.newDelta); - if (Inject.verbose) { - trace(" [was] " + jump.target + - " [now] " + jump.newTarget); - } - break; - } - - default: { - int instrLen = opcLengths[opcode]; - c.writeU1(opcode); // instruction itself - c.copy(instrLen-1); - } - } - } - } - - /** - * Copy the exception table for this method code - */ - void copyExceptionTable() throws IOException { - int tableLength = c.copyU2(); // exception table len - if (tableLength > 0) { - traceln(); - traceln("Exception table:"); - traceln(" from:old/new to:old/new target:old/new type"); - for (int tcnt = tableLength; tcnt > 0; --tcnt) { - int startPC = c.readU2(); - int newStartPC = map[startPC]; - c.writeU2(newStartPC); - int endPC = c.readU2(); - int newEndPC = map[endPC]; - c.writeU2(newEndPC); - int handlerPC = c.readU2(); - int newHandlerPC = map[handlerPC]; - c.writeU2(newHandlerPC); - int catchType = c.copyU2(); - if (Inject.verbose) { - traceFixedWidthInt(startPC, 6); - traceFixedWidthInt(newStartPC, 6); - traceFixedWidthInt(endPC, 6); - traceFixedWidthInt(newEndPC, 6); - traceFixedWidthInt(handlerPC, 6); - traceFixedWidthInt(newHandlerPC, 6); - trace(" "); - if (catchType == 0) - traceln("any"); - else { - traceln("" + catchType); - } - } - } - } - } - - /** - * Copy the line number table for this method code - */ - void copyLineNumberAttr() throws IOException { - // name index already read - c.copy(4); // attr len - int tableLength = c.copyU2(); // line table len - if (tableLength > 0) { - if (Inject.verbose) { - traceln(); - traceln("Line numbers for method " + methodName); - } - for (int tcnt = tableLength; tcnt > 0; --tcnt) { - int startPC = c.readU2(); - int newStartPC = map[startPC]; - c.writeU2(newStartPC); - int lineNumber = c.copyU2(); - if (Inject.verbose) { - traceln(" line " + lineNumber + - ": [was] " + startPC + - " [now] " + newStartPC); - } - } - } - } - - /** - * Copy the local variable table for this method code - */ - void copyLocalVarAttr() throws IOException { - // name index already read - c.copy(4); // attr len - int tableLength = c.copyU2(); // local var table len - if (tableLength > 0) { - if (Inject.verbose) { - traceln(); - traceln("Local variables for method " + methodName); - } - for (int tcnt = tableLength; tcnt > 0; --tcnt) { - int startPC = c.readU2(); - int newStartPC = map[startPC]; - c.writeU2(newStartPC); - int length = c.readU2(); - int endPC = startPC + length; - int newEndPC = map[endPC]; - int newLength = newEndPC - newStartPC; - c.writeU2(newLength); - int nameIndex = c.copyU2(); - int descriptorIndex = c.copyU2(); - int index = c.copyU2(); - if (Inject.verbose) { - trace(" "); - trace(descriptorIndex); - trace(" "); - trace(nameIndex); - traceln(" pc= [was] " + startPC + " [now] " + newStartPC + - ", length= [was] " + length + " [now] " + newLength + - ", slot=" + index); - } - } - } - } -}
--- a/jdk/test/java/lang/instrument/ilib/Injector.java Tue Aug 26 16:42:31 2014 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2005, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package ilib; - -interface Injector { - byte[] bytecodes(String className, String methodName, int location); -}
--- a/jdk/test/java/lang/instrument/ilib/Options.java Tue Aug 26 16:42:31 2014 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2005, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package ilib; - -public class Options { - public boolean shouldInstrumentNew = false; - public boolean shouldInstrumentCall = false; - public boolean shouldInstrumentIndexed = false; - public boolean shouldInstrumentObject = false; - public boolean shouldInstrumentObjectInit = false; - public boolean shouldInstrumentNativeMethods = false; - public String targetMethod = null; - public int fixedIndex = 0; - public String trackerClassName = "MyTracker"; - public String allocTrackerMethodName = "allocTracker"; - public String callTrackerMethodName = "callTracker"; - public String wrappedTrackerMethodName = "wrappedTracker"; - public String wrappedPrefix = "wrapped_up_"; -}
--- a/jdk/test/java/lang/instrument/ilib/RuntimeConstants.java Tue Aug 26 16:42:31 2014 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,732 +0,0 @@ -/* - * Copyright (c) 2005, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package ilib; - -public interface RuntimeConstants { - - /* Signature Characters */ - char SIGC_VOID = 'V'; - String SIG_VOID = "V"; - char SIGC_BOOLEAN = 'Z'; - String SIG_BOOLEAN = "Z"; - char SIGC_BYTE = 'B'; - String SIG_BYTE = "B"; - char SIGC_CHAR = 'C'; - String SIG_CHAR = "C"; - char SIGC_SHORT = 'S'; - String SIG_SHORT = "S"; - char SIGC_INT = 'I'; - String SIG_INT = "I"; - char SIGC_LONG = 'J'; - String SIG_LONG = "J"; - char SIGC_FLOAT = 'F'; - String SIG_FLOAT = "F"; - char SIGC_DOUBLE = 'D'; - String SIG_DOUBLE = "D"; - char SIGC_ARRAY = '['; - String SIG_ARRAY = "["; - char SIGC_CLASS = 'L'; - String SIG_CLASS = "L"; - char SIGC_METHOD = '('; - String SIG_METHOD = "("; - char SIGC_ENDCLASS = ';'; - String SIG_ENDCLASS = ";"; - char SIGC_ENDMETHOD = ')'; - String SIG_ENDMETHOD = ")"; - char SIGC_PACKAGE = '/'; - String SIG_PACKAGE = "/"; - - /* Class File Constants */ - int JAVA_MAGIC = 0xcafebabe; - int JAVA_MIN_SUPPORTED_VERSION = 45; - int JAVA_MAX_SUPPORTED_VERSION = 48; - int JAVA_MAX_SUPPORTED_MINOR_VERSION = 0; - - /* Generate class file version for 1.1 by default */ - int JAVA_DEFAULT_VERSION = 45; - int JAVA_DEFAULT_MINOR_VERSION = 3; - - /* Constant table */ - int CONSTANT_UTF8 = 1; - int CONSTANT_UNICODE = 2; - int CONSTANT_INTEGER = 3; - int CONSTANT_FLOAT = 4; - int CONSTANT_LONG = 5; - int CONSTANT_DOUBLE = 6; - int CONSTANT_CLASS = 7; - int CONSTANT_STRING = 8; - int CONSTANT_FIELD = 9; - int CONSTANT_METHOD = 10; - int CONSTANT_INTERFACEMETHOD = 11; - int CONSTANT_NAMEANDTYPE = 12; - - /* Access and modifier flags */ - int ACC_PUBLIC = 0x00000001; - int ACC_PRIVATE = 0x00000002; - int ACC_PROTECTED = 0x00000004; - int ACC_STATIC = 0x00000008; - int ACC_FINAL = 0x00000010; - int ACC_SYNCHRONIZED = 0x00000020; - int ACC_VOLATILE = 0x00000040; - int ACC_TRANSIENT = 0x00000080; - int ACC_NATIVE = 0x00000100; - int ACC_INTERFACE = 0x00000200; - int ACC_ABSTRACT = 0x00000400; - int ACC_SUPER = 0x00000020; - int ACC_STRICT = 0x00000800; - - /* Type codes */ - int T_CLASS = 0x00000002; - int T_BOOLEAN = 0x00000004; - int T_CHAR = 0x00000005; - int T_FLOAT = 0x00000006; - int T_DOUBLE = 0x00000007; - int T_BYTE = 0x00000008; - int T_SHORT = 0x00000009; - int T_INT = 0x0000000a; - int T_LONG = 0x0000000b; - - /* Opcodes */ - int opc_try = -3; - int opc_dead = -2; - int opc_label = -1; - int opc_nop = 0; - int opc_aconst_null = 1; - int opc_iconst_m1 = 2; - int opc_iconst_0 = 3; - int opc_iconst_1 = 4; - int opc_iconst_2 = 5; - int opc_iconst_3 = 6; - int opc_iconst_4 = 7; - int opc_iconst_5 = 8; - int opc_lconst_0 = 9; - int opc_lconst_1 = 10; - int opc_fconst_0 = 11; - int opc_fconst_1 = 12; - int opc_fconst_2 = 13; - int opc_dconst_0 = 14; - int opc_dconst_1 = 15; - int opc_bipush = 16; - int opc_sipush = 17; - int opc_ldc = 18; - int opc_ldc_w = 19; - int opc_ldc2_w = 20; - int opc_iload = 21; - int opc_lload = 22; - int opc_fload = 23; - int opc_dload = 24; - int opc_aload = 25; - int opc_iload_0 = 26; - int opc_iload_1 = 27; - int opc_iload_2 = 28; - int opc_iload_3 = 29; - int opc_lload_0 = 30; - int opc_lload_1 = 31; - int opc_lload_2 = 32; - int opc_lload_3 = 33; - int opc_fload_0 = 34; - int opc_fload_1 = 35; - int opc_fload_2 = 36; - int opc_fload_3 = 37; - int opc_dload_0 = 38; - int opc_dload_1 = 39; - int opc_dload_2 = 40; - int opc_dload_3 = 41; - int opc_aload_0 = 42; - int opc_aload_1 = 43; - int opc_aload_2 = 44; - int opc_aload_3 = 45; - int opc_iaload = 46; - int opc_laload = 47; - int opc_faload = 48; - int opc_daload = 49; - int opc_aaload = 50; - int opc_baload = 51; - int opc_caload = 52; - int opc_saload = 53; - int opc_istore = 54; - int opc_lstore = 55; - int opc_fstore = 56; - int opc_dstore = 57; - int opc_astore = 58; - int opc_istore_0 = 59; - int opc_istore_1 = 60; - int opc_istore_2 = 61; - int opc_istore_3 = 62; - int opc_lstore_0 = 63; - int opc_lstore_1 = 64; - int opc_lstore_2 = 65; - int opc_lstore_3 = 66; - int opc_fstore_0 = 67; - int opc_fstore_1 = 68; - int opc_fstore_2 = 69; - int opc_fstore_3 = 70; - int opc_dstore_0 = 71; - int opc_dstore_1 = 72; - int opc_dstore_2 = 73; - int opc_dstore_3 = 74; - int opc_astore_0 = 75; - int opc_astore_1 = 76; - int opc_astore_2 = 77; - int opc_astore_3 = 78; - int opc_iastore = 79; - int opc_lastore = 80; - int opc_fastore = 81; - int opc_dastore = 82; - int opc_aastore = 83; - int opc_bastore = 84; - int opc_castore = 85; - int opc_sastore = 86; - int opc_pop = 87; - int opc_pop2 = 88; - int opc_dup = 89; - int opc_dup_x1 = 90; - int opc_dup_x2 = 91; - int opc_dup2 = 92; - int opc_dup2_x1 = 93; - int opc_dup2_x2 = 94; - int opc_swap = 95; - int opc_iadd = 96; - int opc_ladd = 97; - int opc_fadd = 98; - int opc_dadd = 99; - int opc_isub = 100; - int opc_lsub = 101; - int opc_fsub = 102; - int opc_dsub = 103; - int opc_imul = 104; - int opc_lmul = 105; - int opc_fmul = 106; - int opc_dmul = 107; - int opc_idiv = 108; - int opc_ldiv = 109; - int opc_fdiv = 110; - int opc_ddiv = 111; - int opc_irem = 112; - int opc_lrem = 113; - int opc_frem = 114; - int opc_drem = 115; - int opc_ineg = 116; - int opc_lneg = 117; - int opc_fneg = 118; - int opc_dneg = 119; - int opc_ishl = 120; - int opc_lshl = 121; - int opc_ishr = 122; - int opc_lshr = 123; - int opc_iushr = 124; - int opc_lushr = 125; - int opc_iand = 126; - int opc_land = 127; - int opc_ior = 128; - int opc_lor = 129; - int opc_ixor = 130; - int opc_lxor = 131; - int opc_iinc = 132; - int opc_i2l = 133; - int opc_i2f = 134; - int opc_i2d = 135; - int opc_l2i = 136; - int opc_l2f = 137; - int opc_l2d = 138; - int opc_f2i = 139; - int opc_f2l = 140; - int opc_f2d = 141; - int opc_d2i = 142; - int opc_d2l = 143; - int opc_d2f = 144; - int opc_i2b = 145; - int opc_i2c = 146; - int opc_i2s = 147; - int opc_lcmp = 148; - int opc_fcmpl = 149; - int opc_fcmpg = 150; - int opc_dcmpl = 151; - int opc_dcmpg = 152; - int opc_ifeq = 153; - int opc_ifne = 154; - int opc_iflt = 155; - int opc_ifge = 156; - int opc_ifgt = 157; - int opc_ifle = 158; - int opc_if_icmpeq = 159; - int opc_if_icmpne = 160; - int opc_if_icmplt = 161; - int opc_if_icmpge = 162; - int opc_if_icmpgt = 163; - int opc_if_icmple = 164; - int opc_if_acmpeq = 165; - int opc_if_acmpne = 166; - int opc_goto = 167; - int opc_jsr = 168; - int opc_ret = 169; - int opc_tableswitch = 170; - int opc_lookupswitch = 171; - int opc_ireturn = 172; - int opc_lreturn = 173; - int opc_freturn = 174; - int opc_dreturn = 175; - int opc_areturn = 176; - int opc_return = 177; - int opc_getstatic = 178; - int opc_putstatic = 179; - int opc_getfield = 180; - int opc_putfield = 181; - int opc_invokevirtual = 182; - int opc_invokespecial = 183; - int opc_invokestatic = 184; - int opc_invokeinterface = 185; - int opc_xxxunusedxxx = 186; - int opc_new = 187; - int opc_newarray = 188; - int opc_anewarray = 189; - int opc_arraylength = 190; - int opc_athrow = 191; - int opc_checkcast = 192; - int opc_instanceof = 193; - int opc_monitorenter = 194; - int opc_monitorexit = 195; - int opc_wide = 196; - int opc_multianewarray = 197; - int opc_ifnull = 198; - int opc_ifnonnull = 199; - int opc_goto_w = 200; - int opc_jsr_w = 201; - int opc_breakpoint = 202; - - /* Opcode Names */ - String opcNames[] = { - "nop", - "aconst_null", - "iconst_m1", - "iconst_0", - "iconst_1", - "iconst_2", - "iconst_3", - "iconst_4", - "iconst_5", - "lconst_0", - "lconst_1", - "fconst_0", - "fconst_1", - "fconst_2", - "dconst_0", - "dconst_1", - "bipush", - "sipush", - "ldc", - "ldc_w", - "ldc2_w", - "iload", - "lload", - "fload", - "dload", - "aload", - "iload_0", - "iload_1", - "iload_2", - "iload_3", - "lload_0", - "lload_1", - "lload_2", - "lload_3", - "fload_0", - "fload_1", - "fload_2", - "fload_3", - "dload_0", - "dload_1", - "dload_2", - "dload_3", - "aload_0", - "aload_1", - "aload_2", - "aload_3", - "iaload", - "laload", - "faload", - "daload", - "aaload", - "baload", - "caload", - "saload", - "istore", - "lstore", - "fstore", - "dstore", - "astore", - "istore_0", - "istore_1", - "istore_2", - "istore_3", - "lstore_0", - "lstore_1", - "lstore_2", - "lstore_3", - "fstore_0", - "fstore_1", - "fstore_2", - "fstore_3", - "dstore_0", - "dstore_1", - "dstore_2", - "dstore_3", - "astore_0", - "astore_1", - "astore_2", - "astore_3", - "iastore", - "lastore", - "fastore", - "dastore", - "aastore", - "bastore", - "castore", - "sastore", - "pop", - "pop2", - "dup", - "dup_x1", - "dup_x2", - "dup2", - "dup2_x1", - "dup2_x2", - "swap", - "iadd", - "ladd", - "fadd", - "dadd", - "isub", - "lsub", - "fsub", - "dsub", - "imul", - "lmul", - "fmul", - "dmul", - "idiv", - "ldiv", - "fdiv", - "ddiv", - "irem", - "lrem", - "frem", - "drem", - "ineg", - "lneg", - "fneg", - "dneg", - "ishl", - "lshl", - "ishr", - "lshr", - "iushr", - "lushr", - "iand", - "land", - "ior", - "lor", - "ixor", - "lxor", - "iinc", - "i2l", - "i2f", - "i2d", - "l2i", - "l2f", - "l2d", - "f2i", - "f2l", - "f2d", - "d2i", - "d2l", - "d2f", - "i2b", - "i2c", - "i2s", - "lcmp", - "fcmpl", - "fcmpg", - "dcmpl", - "dcmpg", - "ifeq", - "ifne", - "iflt", - "ifge", - "ifgt", - "ifle", - "if_icmpeq", - "if_icmpne", - "if_icmplt", - "if_icmpge", - "if_icmpgt", - "if_icmple", - "if_acmpeq", - "if_acmpne", - "goto", - "jsr", - "ret", - "tableswitch", - "lookupswitch", - "ireturn", - "lreturn", - "freturn", - "dreturn", - "areturn", - "return", - "getstatic", - "putstatic", - "getfield", - "putfield", - "invokevirtual", - "invokespecial", - "invokestatic", - "invokeinterface", - "xxxunusedxxx", - "new", - "newarray", - "anewarray", - "arraylength", - "athrow", - "checkcast", - "instanceof", - "monitorenter", - "monitorexit", - "wide", - "multianewarray", - "ifnull", - "ifnonnull", - "goto_w", - "jsr_w", - "breakpoint" - }; - - /* Opcode Lengths */ - int opcLengths[] = { - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 3, - 2, - 3, - 3, - 2, - 2, - 2, - 2, - 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 2, - 99, - 99, - 1, - 1, - 1, - 1, - 1, - 1, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 5, - 0, - 3, - 2, - 3, - 1, - 1, - 3, - 3, - 1, - 1, - 0, - 4, - 3, - 3, - 5, - 5, - 1 - }; - -}