diff --git a/nbproject/genfiles.properties b/nbproject/genfiles.properties new file mode 100644 index 000000000..ef429c4a9 --- /dev/null +++ b/nbproject/genfiles.properties @@ -0,0 +1,5 @@ +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/jdk.xml.data.CRC32=f99b410e +nbproject/jdk.xml.script.CRC32=5342cb35 +nbproject/jdk.xml.stylesheet.CRC32=b5c68e1e@1.38.1 diff --git a/nbproject/ide-file-targets.xml b/nbproject/ide-file-targets.xml index 04ce8f764..3be35ad4a 100644 --- a/nbproject/ide-file-targets.xml +++ b/nbproject/ide-file-targets.xml @@ -41,7 +41,7 @@ Must set property 'run.class' +path="test-lib/junit-4.6.jar;test-lib/asm-${asm.version}.jar;test-lib/asm-all-${asm.version}.jar;test-lib/ant-junit.jar;"/> @@ -62,7 +62,7 @@ value="-Xrunjdwp:transport=dt_socket,address=${jpda.address},suspend=y"/>--> Must set property 'run.class' +path="test-lib/junit-4.6.jar;test-lib/asm-${asm.version}.jar;test-lib/asm-all-${asm.version}.jar;test-lib/ant-junit.jar;"/> diff --git a/nbproject/jdk.xml b/nbproject/jdk.xml new file mode 100644 index 000000000..237e529b4 --- /dev/null +++ b/nbproject/jdk.xml @@ -0,0 +1,157 @@ + + + + + Permits selection of a JDK to use when building and running project. + See: http://www.netbeans.org/issues/show_bug.cgi?id=64160 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + nbjdk.active=${nbjdk.active} nbjdk.home=${nbjdk.home} nbjdk.java=${nbjdk.java} nbjdk.javac=${nbjdk.javac} nbjdk.javadoc=${nbjdk.javadoc} nbjdk.bootclasspath=${nbjdk.bootclasspath} nbjdk.valid=${nbjdk.valid} have-jdk-1.4=${have-jdk-1.4} have-jdk-1.5=${have-jdk-1.5} + + + + + Warning: nbjdk.active=${nbjdk.active} or nbjdk.home=${nbjdk.home} is an invalid Java platform; ignoring and using ${jdkhome.presumed} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nbproject/nbjdk.properties b/nbproject/nbjdk.properties new file mode 100644 index 000000000..3033a8abb --- /dev/null +++ b/nbproject/nbjdk.properties @@ -0,0 +1 @@ +nbjdk.active=default_platform diff --git a/nbproject/nbjdk.xml b/nbproject/nbjdk.xml new file mode 100644 index 000000000..4fc6ecf3f --- /dev/null +++ b/nbproject/nbjdk.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nbproject/project.xml b/nbproject/project.xml index bc43e29e9..18d043a93 100755 --- a/nbproject/project.xml +++ b/nbproject/project.xml @@ -41,28 +41,28 @@ - + jar - + clean - + clean jar - + test - + javadoc - + debug-selected-file-in-classes debug.class @@ -75,7 +75,7 @@ - + run-selected-file-in-classes run.class @@ -88,7 +88,7 @@ - + debug-selected-file-in-test debug.class @@ -101,7 +101,7 @@ - + run-selected-file-in-test run.class @@ -114,7 +114,7 @@ - + compile-selected-btrace-files files @@ -127,7 +127,7 @@ - + compile-selected-files-in-test files @@ -140,7 +140,7 @@ - + compile-selected-files-in-classes files @@ -156,13 +156,13 @@ folder build/classes - + jar folder build/test - + jar @@ -233,7 +233,7 @@ src/test - build/classes:test-lib/asm-${asm.version}.jar:lib/btrace-asm-${asm.version}.jar:test-lib/asm-util-${asm.version}.jar:${junit.jar} + build/classes:test-lib/asm-${asm.version}.jar:lib/btrace-asm-${asm.version}.jar:test-lib/asm-all-${asm.version}.jar:${junit.jar} build/test 1.5 diff --git a/src/share/classes/com/sun/btrace/BTraceRuntime.java b/src/share/classes/com/sun/btrace/BTraceRuntime.java index 676a4411c..7029ae8e3 100755 --- a/src/share/classes/com/sun/btrace/BTraceRuntime.java +++ b/src/share/classes/com/sun/btrace/BTraceRuntime.java @@ -1005,8 +1005,11 @@ public static void retransform(String runtimeName, Class clazz) { if (rt != null && rt.instrumentation.isModifiableClass(clazz)) { rt.instrumentation.retransformClasses(clazz); } - } catch (Exception e) { - e.printStackTrace(); + } catch (Throwable e) { + if (e instanceof VerifyError) { + System.out.println("btrace DEBUG: " + ((VerifyError)e).getMessage()); + } + e.printStackTrace(System.out); } } diff --git a/src/share/classes/com/sun/btrace/agent/Client.java b/src/share/classes/com/sun/btrace/agent/Client.java index 65ee0ad5e..73aea5614 100755 --- a/src/share/classes/com/sun/btrace/agent/Client.java +++ b/src/share/classes/com/sun/btrace/agent/Client.java @@ -1,12 +1,12 @@ /* - * Copyright 2008-2010 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2008-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. Sun designates this + * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or @@ -18,9 +18,9 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * 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 com.sun.btrace.agent; @@ -54,6 +54,8 @@ import com.sun.btrace.runtime.OnMethod; import com.sun.btrace.runtime.OnProbe; import com.sun.btrace.runtime.RunnableGeneratorImpl; +import com.sun.btrace.util.templates.impl.CallTimeStampExpander; +import com.sun.btrace.util.templates.impl.MethodTimeStampExpander; import java.lang.annotation.Annotation; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; @@ -90,6 +92,8 @@ abstract class Client implements ClassFileTransformer, CommandListener { AnnotationParser.class.getClass(); AnnotationType.class.getClass(); Annotation.class.getClass(); + MethodTimeStampExpander.class.getClass(); + CallTimeStampExpander.class.getClass(); BTraceRuntime.init(createPerfReaderImpl(), new RunnableGeneratorImpl()); } diff --git a/src/share/classes/com/sun/btrace/runtime/ClassFilter.java b/src/share/classes/com/sun/btrace/runtime/ClassFilter.java index 064ce2543..0a2ed175f 100755 --- a/src/share/classes/com/sun/btrace/runtime/ClassFilter.java +++ b/src/share/classes/com/sun/btrace/runtime/ClassFilter.java @@ -77,9 +77,18 @@ public boolean isCandidate(Class target) { return false; } - // ignore classes annotated with @BTrace - - // We don't want to instrument tracing classes! - if (target.getAnnotation(BTrace.class) != null) { + try { + // ignore classes annotated with @BTrace - + // We don't want to instrument tracing classes! + if (target.getAnnotation(BTrace.class) != null) { + return false; + } + } catch (NullPointerException e) { + // thrown from java.lang.Class.initAnnotationsIfNecessary() + // seems to be a case when trying to access non-existing annotations + // on a superclass + // * messed up situation - ignore the class * + return false; } diff --git a/src/share/classes/com/sun/btrace/runtime/ClinitInjector.java b/src/share/classes/com/sun/btrace/runtime/ClinitInjector.java index 622dad2ac..dcc92942d 100644 --- a/src/share/classes/com/sun/btrace/runtime/ClinitInjector.java +++ b/src/share/classes/com/sun/btrace/runtime/ClinitInjector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011-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 @@ -56,7 +56,7 @@ public boolean isTransformed() { @Override public void visit(int version, int access, String name, String signature, String supername, String[] interfaces) { - if (!(((access & (Opcodes.ACC_INTERFACE | Opcodes.ACC_ANNOTATION)) != 0) || + if (!(((access & (Opcodes.ACC_INTERFACE | Opcodes.ACC_ANNOTATION | Opcodes.ACC_FINAL)) != 0) || (supername.equals("java/lang/Object") && interfaces.length == 0))) { transformed = true; } diff --git a/src/share/classes/com/sun/btrace/runtime/ErrorReturnInstrumentor.java b/src/share/classes/com/sun/btrace/runtime/ErrorReturnInstrumentor.java index ee1b6dba7..b7a70a970 100755 --- a/src/share/classes/com/sun/btrace/runtime/ErrorReturnInstrumentor.java +++ b/src/share/classes/com/sun/btrace/runtime/ErrorReturnInstrumentor.java @@ -49,20 +49,28 @@ * * @author A. Sundararajan */ -public class ErrorReturnInstrumentor extends MethodEntryInstrumentor { - private Label start = new Label(); - private Label end = new Label(); +abstract public class ErrorReturnInstrumentor extends MethodEntryInstrumentor { + private final Label start = new Label(); + private final Label end = new Label(); public ErrorReturnInstrumentor(LocalVariableHelper mv, String parentClz, String superClz, int access, String name, String desc) { super(mv, parentClz, superClz, access, name, desc); } - public void visitCode() { + @Override + protected void visitMethodPrologue() { + generateEntryTimeStamp(); visitLabel(start); - super.visitCode(); } + @Override + protected void onMethodEntry() { + } + + abstract protected void generateEntryTimeStamp(); + + @Override public void visitMaxs(int maxStack, int maxLocals) { visitLabel(end); visitTryCatchBlock(start, end, end, JAVA_LANG_THROWABLE); @@ -92,7 +100,10 @@ public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); - return new ErrorReturnInstrumentor(new LocalVariableHelperImpl(mv, access, desc), args[0], args[0], access, name, desc); + return new ErrorReturnInstrumentor(new LocalVariableHelperImpl(mv, access, desc), args[0], args[0], access, name, desc) { + @Override + protected void generateEntryTimeStamp() {} + }; } }); fos.write(writer.toByteArray()); diff --git a/src/share/classes/com/sun/btrace/runtime/Instrumentor.java b/src/share/classes/com/sun/btrace/runtime/Instrumentor.java index 3117ea2ef..c23e8055c 100755 --- a/src/share/classes/com/sun/btrace/runtime/Instrumentor.java +++ b/src/share/classes/com/sun/btrace/runtime/Instrumentor.java @@ -175,24 +175,24 @@ public MethodVisitor visitMethod(final int access, final String name, MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions); + LocalVariableHelperImpl lvs = new LocalVariableHelperImpl(methodVisitor, access, desc); + + TemplateExpanderVisitor tse = new TemplateExpanderVisitor( + lvs, className, name, desc + ); + if (applicableOnMethods.isEmpty() || (access & ACC_ABSTRACT) != 0 || (access & ACC_NATIVE) != 0 || name.startsWith(BTRACE_METHOD_PREFIX)) { - return methodVisitor; + return tse; } if (name.equals(TimeStampHelper.TIME_STAMP_NAME)) { timeStampExisting = true; - return methodVisitor; + return tse; } - LocalVariableHelperImpl lvs = new LocalVariableHelperImpl(methodVisitor, access, desc); - - TemplateExpanderVisitor tse = new TemplateExpanderVisitor( - lvs, className, name, desc - ); - LocalVariableHelper visitor = tse; for (OnMethod om : applicableOnMethods) { @@ -384,6 +384,7 @@ protected void onAfterArrayStore(int opcode) { };// case CALL: + // return new MethodCallInstrumentor(mv, className, superName, access, name, desc) { private final String localClassName = loc.getClazz(); @@ -676,7 +677,7 @@ public void doProvide() { private boolean generatingCode = false; @Override - protected void onMethodEntry() { + protected void generateEntryTimeStamp() { if (vr.isValid()) { if (om.getDurationParameter() != -1) { try { @@ -865,43 +866,56 @@ && matches(targetFieldName, name)) { case INSTANCEOF: // return new TypeCheckInstrumentor(mv, className, superName, access, name, desc) { + ValidationResult vr; + Type castType = TypeUtils.objectType; + int castTypeIndex = -1; + + { + addExtraTypeInfo(om.getSelfParameter(), Type.getObjectType(className)); + } private void callAction(int opcode, String desc) { - if (opcode == Opcodes.INSTANCEOF) { - // TODO not really usefull - // It would be better to check for the original and desired type - Type castType = Type.getObjectType(desc); - addExtraTypeInfo(om.getSelfParameter(), Type.getObjectType(className)); - ValidationResult vr = validateArguments(om, isStatic(), actionArgTypes, new Type[]{castType}); - if (vr.isValid()) { - int castTypeIndex = -1; - if (!vr.isAny()) { - dup(); - castTypeIndex = storeNewLocal(castType); - } + // TODO not really usefull + // It would be better to check for the original and desired type - loadArguments( - new LocalVarArgProvider(vr.getArgIdx(0), castType, castTypeIndex), - new ConstantArgProvider(om.getClassNameParameter(), className.replace("/", ".")), - new ConstantArgProvider(om.getMethodParameter(), getName(om.isMethodFqn())), - new LocalVarArgProvider(om.getSelfParameter(), Type.getObjectType(className), 0)); + if (vr.isValid()) { + loadArguments( + new LocalVarArgProvider(vr.getArgIdx(0), castType, castTypeIndex), + new ConstantArgProvider(om.getClassNameParameter(), className.replace("/", ".")), + new ConstantArgProvider(om.getMethodParameter(), getName(om.isMethodFqn())), + new LocalVarArgProvider(om.getSelfParameter(), Type.getObjectType(className), 0)); - invokeBTraceAction(this, om); - } + invokeBTraceAction(this, om); } } @Override protected void onBeforeTypeCheck(int opcode, String desc) { - if (where == Where.BEFORE) { - callAction(opcode, desc); + if (opcode == Opcodes.INSTANCEOF) { + castType = Type.getObjectType(desc); + vr = validateArguments(om, isStatic(), actionArgTypes, new Type[]{castType}); + if (vr.isValid()) { + if (!vr.isAny()) { + dup(); + castTypeIndex = storeNewLocal(castType); + } + if (where == Where.BEFORE) { + callAction(opcode, desc); + } + } } } @Override protected void onAfterTypeCheck(int opcode, String desc) { - if (where == Where.AFTER) { - callAction(opcode, desc); + if (opcode == Opcodes.INSTANCEOF) { + castType = Type.getObjectType(desc); + vr = validateArguments(om, isStatic(), actionArgTypes, new Type[]{castType}); + if (vr.isValid()) { + if (where == Where.AFTER) { + callAction(opcode, desc); + } + } } } };// diff --git a/src/share/classes/com/sun/btrace/runtime/MethodEntryExitInstrumentor.java b/src/share/classes/com/sun/btrace/runtime/MethodEntryExitInstrumentor.java index e8f9a6a80..1d9adf3ab 100755 --- a/src/share/classes/com/sun/btrace/runtime/MethodEntryExitInstrumentor.java +++ b/src/share/classes/com/sun/btrace/runtime/MethodEntryExitInstrumentor.java @@ -45,7 +45,7 @@ * * @author A. Sundararajan */ -public class MethodEntryExitInstrumentor extends ErrorReturnInstrumentor { +abstract public class MethodEntryExitInstrumentor extends ErrorReturnInstrumentor { private boolean isConstructor; private boolean entryCalled; @@ -55,27 +55,6 @@ public MethodEntryExitInstrumentor(LocalVariableHelper mv, String parentClz, Str isConstructor = name.equals(CONSTRUCTOR); } - public void visitCode() { - if (!isConstructor) { - entryCalled = true; - onMethodEntry(); - } - super.visitCode(); - } - - public void visitMethodInsn(int opcode, - String owner, - String name, - String desc) { - super.visitMethodInsn(opcode, owner, name, desc); - if (isConstructor && !entryCalled && name.equals(CONSTRUCTOR)) { - // super or this class constructor call. - // do method entry after that! - entryCalled = true; - onMethodEntry(); - } - } - public void visitInsn(int opcode) { switch (opcode) { case IRETURN: @@ -86,7 +65,7 @@ public void visitInsn(int opcode) { case RETURN: if (!entryCalled) { entryCalled = true; - onMethodEntry(); + doMethodEntry(); } onMethodReturn(opcode); break; @@ -96,18 +75,10 @@ public void visitInsn(int opcode) { super.visitInsn(opcode); } - protected void onMethodEntry() { - println("on method entry"); - } - protected void onMethodReturn(int opcode) { println("on method return"); } - protected void onErrorReturn() { - println("on method error return"); - } - public static void main(final String[] args) throws Exception { if (args.length != 1) { System.err.println("Usage: java com.sun.btrace.runtime.ErrorReturnInstrumentor "); @@ -125,7 +96,10 @@ public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); - return new MethodEntryExitInstrumentor(new LocalVariableHelperImpl(mv, access, desc), args[0], args[0], access, name, desc); + return new MethodEntryExitInstrumentor(new LocalVariableHelperImpl(mv, access, desc), args[0], args[0], access, name, desc) { + @Override + protected void generateEntryTimeStamp() {} + }; } }); fos.write(writer.toByteArray()); diff --git a/src/share/classes/com/sun/btrace/runtime/MethodEntryInstrumentor.java b/src/share/classes/com/sun/btrace/runtime/MethodEntryInstrumentor.java index 8862b5d7a..a7dc931b8 100755 --- a/src/share/classes/com/sun/btrace/runtime/MethodEntryInstrumentor.java +++ b/src/share/classes/com/sun/btrace/runtime/MethodEntryInstrumentor.java @@ -53,14 +53,19 @@ public MethodEntryInstrumentor(LocalVariableHelper mv, String parentClz, String super(mv, parentClz, superClz, access, name, desc); } - public void visitCode() { + final public void visitCode() { if (!isConstructor()) { entryCalled = true; - onMethodEntry(); + doMethodEntry(); } super.visitCode(); } + final protected void doMethodEntry() { + visitMethodPrologue(); + onMethodEntry(); + } + public void visitMethodInsn(int opcode, String owner, String name, @@ -71,7 +76,7 @@ public void visitMethodInsn(int opcode, // super or this class constructor call. // do method entry after that! entryCalled = true; - onMethodEntry(); + doMethodEntry(); } } } @@ -99,6 +104,8 @@ protected void onMethodEntry() { println("entering " + getName() + getDescriptor()); } + protected void visitMethodPrologue() {} + public static void main(final String[] args) throws Exception { if (args.length != 1) { System.err.println("Usage: java com.sun.btrace.runtime.MethodEntryInstrumentor "); diff --git a/src/share/classes/com/sun/btrace/runtime/SynchronizedInstrumentor.java b/src/share/classes/com/sun/btrace/runtime/SynchronizedInstrumentor.java index 3214beb28..f3df1118e 100755 --- a/src/share/classes/com/sun/btrace/runtime/SynchronizedInstrumentor.java +++ b/src/share/classes/com/sun/btrace/runtime/SynchronizedInstrumentor.java @@ -25,7 +25,6 @@ package com.sun.btrace.runtime; -import com.sun.btrace.annotations.Where; import com.sun.btrace.org.objectweb.asm.*; import java.io.BufferedInputStream; import java.io.FileInputStream; @@ -33,8 +32,6 @@ import static com.sun.btrace.org.objectweb.asm.Opcodes.*; import com.sun.btrace.util.LocalVariableHelperImpl; import com.sun.btrace.util.LocalVariableHelper; -import java.util.EnumSet; -import java.util.Set; /** * This visitor helps in inserting code whenever a synchronized @@ -57,6 +54,11 @@ public SynchronizedInstrumentor( isSyncMethod = (access & ACC_SYNCHRONIZED) != 0; } + @Override + protected void generateEntryTimeStamp() { + // no timestamp collection + } + @Override protected void onMethodEntry() { if (isSyncMethod) { diff --git a/src/share/classes/com/sun/btrace/runtime/TypeUtils.java b/src/share/classes/com/sun/btrace/runtime/TypeUtils.java index a4043b8ca..d8f92df4d 100755 --- a/src/share/classes/com/sun/btrace/runtime/TypeUtils.java +++ b/src/share/classes/com/sun/btrace/runtime/TypeUtils.java @@ -68,6 +68,10 @@ public static boolean isString(Type t) { return t.equals(stringType); } + public static boolean isArray(Type t) { + return t.getInternalName().startsWith("["); + } + public static boolean isThrowable(Type t) { return t.equals(throwableType); } @@ -77,7 +81,7 @@ public static boolean isThrowable(Type t) { * Two types are compatible when and only when: *
    *
  1. They are exactly the same
  2. - *
  3. The left parameter is {@linkplain Object} or {@linkplain AnyType} and + *
  4. The left parameter is {@linkplain Object} or {@linkplain AnyType} and * the right parameter is either {@linkplain Object} or an array
  5. *
  6. The left parameter is assignable from the right one (is a superclass of the right one)
  7. *
@@ -88,9 +92,11 @@ public static boolean isThrowable(Type t) { public static boolean isCompatible(Type left, Type right) { if (left.equals(right)) { return true; + } else if (isArray(left)) { + return false; } else if(isObjectOrAnyType(left)) { int sort2 = right.getSort(); - return (sort2 == Type.OBJECT || sort2 == Type.ARRAY); + return (sort2 == Type.OBJECT || sort2 == Type.ARRAY); } else { ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (cl == null) { @@ -131,7 +137,7 @@ public static boolean isCompatible(Type[] args1, Type[] args2) { * then we allow it - because AnyType is mapped to * java.lang.Object. */ - if (isAnyType(args1[i]) && + if (isAnyType(args1[i]) && (sort2 == Type.OBJECT || sort2 == Type.ARRAY)) { continue; } else { @@ -144,31 +150,31 @@ public static boolean isCompatible(Type[] args1, Type[] args2) { public static Type getArrayType(int arrayOpcode) { switch (arrayOpcode) { - case IALOAD: - case IASTORE: + case IALOAD: + case IASTORE: return Type.getType("[I"); case BALOAD: case BASTORE: return Type.getType("[B"); - case AALOAD: + case AALOAD: case AASTORE: return objectArrayType; case CALOAD: - case CASTORE: + case CASTORE: return Type.getType("[C"); case FALOAD: - case FASTORE: + case FASTORE: return Type.getType("[F"); case SALOAD: - case SASTORE: + case SASTORE: return Type.getType("[S"); - case LALOAD: + case LALOAD: case LASTORE: return Type.getType("[J"); @@ -176,38 +182,38 @@ public static Type getArrayType(int arrayOpcode) { case DASTORE: return Type.getType("[D"); - default: + default: throw new RuntimeException("invalid array opcode"); } } public static Type getElementType(int arrayOpcode) { switch (arrayOpcode) { - case IALOAD: - case IASTORE: + case IALOAD: + case IASTORE: return Type.INT_TYPE; case BALOAD: case BASTORE: return Type.BYTE_TYPE; - case AALOAD: + case AALOAD: case AASTORE: return objectType; case CALOAD: - case CASTORE: + case CASTORE: return Type.CHAR_TYPE; case FALOAD: - case FASTORE: + case FASTORE: return Type.FLOAT_TYPE; case SALOAD: - case SASTORE: + case SASTORE: return Type.SHORT_TYPE; - case LALOAD: + case LALOAD: case LASTORE: return Type.LONG_TYPE; @@ -215,7 +221,7 @@ public static Type getElementType(int arrayOpcode) { case DASTORE: return Type.DOUBLE_TYPE; - default: + default: throw new RuntimeException("invalid array opcode"); } } @@ -271,7 +277,7 @@ public static String declarationToDescriptor(String decl) { } buf.append(descriptor); return buf.toString(); - } + } public static String getJavaType(String desc) { int arrIndex = desc.lastIndexOf("[") + 1; @@ -313,5 +319,5 @@ public static String objectOrArrayType(String type) { buf.append(';'); } return buf.toString(); - } + } } diff --git a/src/share/classes/com/sun/btrace/util/LocalVariableHelper.java b/src/share/classes/com/sun/btrace/util/LocalVariableHelper.java index 9874bf979..1835ac7ad 100644 --- a/src/share/classes/com/sun/btrace/util/LocalVariableHelper.java +++ b/src/share/classes/com/sun/btrace/util/LocalVariableHelper.java @@ -1,7 +1,26 @@ /* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 com.sun.btrace.util; @@ -9,8 +28,9 @@ import com.sun.btrace.org.objectweb.asm.Type; /** - * - * @author jbachorik + * This interface will be implemented by a visitor able to + * create new variables on the fly. + * @author Jaroslav Bachorik */ public interface LocalVariableHelper { int storeNewLocal(Type type); diff --git a/src/share/classes/com/sun/btrace/util/SamplingSupport.java b/src/share/classes/com/sun/btrace/util/SamplingSupport.java index 2f6270988..c4cd44ae6 100644 --- a/src/share/classes/com/sun/btrace/util/SamplingSupport.java +++ b/src/share/classes/com/sun/btrace/util/SamplingSupport.java @@ -24,7 +24,9 @@ */ package com.sun.btrace.util; +import java.lang.reflect.Method; import java.util.Arrays; +import java.util.Random; import java.util.concurrent.ThreadLocalRandom; /** @@ -34,9 +36,46 @@ * @author Jaroslav Bachorik */ final public class SamplingSupport { + private static interface RandomIntProvider { + int nextInt(int bound); + } + + private static final class SharedRandomIntProvider implements RandomIntProvider { + private final Random rnd = new Random(System.nanoTime()); + + public int nextInt(int bound) { + return rnd.nextInt(bound); + } + } + + private static final class ThreadLocalRandomIntProvider implements RandomIntProvider { + public int nextInt(int bound) { + return ThreadLocalRandom.current().nextInt(bound); + } + } + private static final ThreadLocal iCounters = new ThreadLocal(); + private static Method nextIntMtd; + private static Object threadLocalRandom; + + private static final RandomIntProvider rndIntProvider; + + static { + Class clz = null; + try { + clz = Class.forName("java.util.concurrent.ThreadLocalRandom"); + } catch (Throwable e) { + // ThreadLocalRandom not accessible -> pre JDK8 + } + if (clz != null) { + rndIntProvider = new ThreadLocalRandomIntProvider(); + } else { + rndIntProvider = new SharedRandomIntProvider(); + } + } + /** * Used from the injected code to figure out whether it should record the invocation. * @param rate On average each "rate"-th invocation will be recorded @@ -55,7 +94,7 @@ public static boolean sampleHit(int rate, int methodId) { } } if (sampleCntrs[methodId] == 0) { - sampleCntrs[methodId] = ThreadLocalRandom.current().nextInt(rate); + sampleCntrs[methodId] = rndIntProvider.nextInt(rate); return true; } diff --git a/src/share/classes/com/sun/btrace/util/templates/Template.java b/src/share/classes/com/sun/btrace/util/templates/Template.java index 819402c58..ee12d80b4 100644 --- a/src/share/classes/com/sun/btrace/util/templates/Template.java +++ b/src/share/classes/com/sun/btrace/util/templates/Template.java @@ -38,7 +38,7 @@ * @since 1.3 */ public final class Template { - private final String owner = "BTrace$Templates"; + private final String owner = "com/sun/btrace/Templates"; private final String name; private final String sig; private final Set tags = new HashSet(); diff --git a/src/share/classes/com/sun/btrace/util/templates/TemplateExpanderVisitor.java b/src/share/classes/com/sun/btrace/util/templates/TemplateExpanderVisitor.java index c633c05dd..a46d9c51a 100644 --- a/src/share/classes/com/sun/btrace/util/templates/TemplateExpanderVisitor.java +++ b/src/share/classes/com/sun/btrace/util/templates/TemplateExpanderVisitor.java @@ -1,12 +1,12 @@ /* - * Copyright 2008-2010 Sun Microsystems, Inc. All Rights Reserved. + * 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. Sun designates this + * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or @@ -18,18 +18,21 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * 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 com.sun.btrace.util.templates; +import com.sun.btrace.org.objectweb.asm.AnnotationVisitor; +import com.sun.btrace.org.objectweb.asm.Attribute; import com.sun.btrace.org.objectweb.asm.Handle; import com.sun.btrace.org.objectweb.asm.Label; import com.sun.btrace.org.objectweb.asm.MethodVisitor; import com.sun.btrace.org.objectweb.asm.Opcodes; import com.sun.btrace.org.objectweb.asm.Type; +import com.sun.btrace.org.objectweb.asm.TypePath; import com.sun.btrace.util.LocalVariableHelper; import com.sun.btrace.util.templates.impl.CallTimeStampExpander; import com.sun.btrace.util.templates.impl.MethodTimeStampExpander; @@ -62,7 +65,7 @@ public int storeNewLocal(Type type) { @Override public void visitCode() { - super.visitCode(); //To change body of generated methods, choose Tools | Templates. + super.visitCode(); } @Override @@ -85,74 +88,184 @@ public void visitMethodInsn(int opcode, String owner, String name, String desc, @Override public void visitVarInsn(int opcode, int var) { - expandTemplate(null); - super.visitVarInsn(opcode, var); + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitVarInsn(opcode, var); + } } @Override public void visitMultiANewArrayInsn(String string, int i) { - expandTemplate(null); - super.visitMultiANewArrayInsn(string, i); //To change body of generated methods, choose Tools | Templates. + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitMultiANewArrayInsn(string, i); + } } @Override public void visitLookupSwitchInsn(Label label, int[] ints, Label[] labels) { - expandTemplate(null); - super.visitLookupSwitchInsn(label, ints, labels); //To change body of generated methods, choose Tools | Templates. + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitLookupSwitchInsn(label, ints, labels); + } } @Override public void visitTableSwitchInsn(int i, int i1, Label label, Label... labels) { - expandTemplate(null); - super.visitTableSwitchInsn(i, i1, label, labels); //To change body of generated methods, choose Tools | Templates. + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitTableSwitchInsn(i, i1, label, labels); + } } @Override public void visitIincInsn(int i, int i1) { - expandTemplate(null); - super.visitIincInsn(i, i1); //To change body of generated methods, choose Tools | Templates. + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitIincInsn(i, i1); + } } @Override public void visitLdcInsn(Object o) { - expandTemplate(null); - super.visitLdcInsn(o); //To change body of generated methods, choose Tools | Templates. + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitLdcInsn(o); + } } @Override public void visitJumpInsn(int i, Label label) { - expandTemplate(null); - super.visitJumpInsn(i, label); //To change body of generated methods, choose Tools | Templates. + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitJumpInsn(i, label); + } } @Override public void visitInvokeDynamicInsn(String string, String string1, Handle handle, Object... os) { - expandTemplate(null); - super.visitInvokeDynamicInsn(string, string1, handle, os); //To change body of generated methods, choose Tools | Templates. + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitInvokeDynamicInsn(string, string1, handle, os); + } } @Override public void visitFieldInsn(int i, String string, String string1, String string2) { - expandTemplate(null); - super.visitFieldInsn(i, string, string1, string2); //To change body of generated methods, choose Tools | Templates. + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitFieldInsn(i, string, string1, string2); + } } @Override public void visitTypeInsn(int i, String string) { - expandTemplate(null); - super.visitTypeInsn(i, string); //To change body of generated methods, choose Tools | Templates. + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitTypeInsn(i, string); + } } @Override public void visitIntInsn(int i, int i1) { - expandTemplate(null); - super.visitIntInsn(i, i1); //To change body of generated methods, choose Tools | Templates. + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitIntInsn(i, i1); + } } @Override public void visitInsn(int i) { - expandTemplate(null); - super.visitInsn(i); //To change body of generated methods, choose Tools | Templates. + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitInsn(i); + } + } + + @Override + public void visitLineNumber(int i, Label label) { + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitLineNumber(i, label); + } + } + + @Override + public AnnotationVisitor visitLocalVariableAnnotation(int i, TypePath tp, Label[] labels, Label[] labels1, int[] ints, String string, boolean bln) { + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + return super.visitLocalVariableAnnotation(i, tp, labels, labels1, ints, string, bln); + } + return null; + } + + @Override + public void visitLocalVariable(String string, String string1, String string2, Label label, Label label1, int i) { + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitLocalVariable(string, string1, string2, label, label1, i); + } + } + + @Override + public AnnotationVisitor visitTryCatchAnnotation(int i, TypePath tp, String string, boolean bln) { + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + return super.visitTryCatchAnnotation(i, tp, string, bln); + } + return null; + } + + @Override + public void visitTryCatchBlock(Label label, Label label1, Label label2, String string) { + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitTryCatchBlock(label, label1, label2, string); + } + } + + @Override + public AnnotationVisitor visitInsnAnnotation(int i, TypePath tp, String string, boolean bln) { + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + return super.visitInsnAnnotation(i, tp, string, bln); + } + return null; + } + + @Override + public void visitLabel(Label label) { + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitLabel(label); + } + } + + @Override + public void visitAttribute(Attribute atrbt) { + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitAttribute(atrbt); + } + } + + @Override + public AnnotationVisitor visitParameterAnnotation(int i, String string, boolean bln) { + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + return super.visitParameterAnnotation(i, string, bln); + } + return null; + } + + @Override + public AnnotationVisitor visitTypeAnnotation(int i, TypePath tp, String string, boolean bln) { + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + return super.visitTypeAnnotation(i, tp, string, bln); + } + return null; + } + + @Override + public AnnotationVisitor visitAnnotation(String string, boolean bln) { + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + return super.visitAnnotation(string, bln); + } + return null; + } + + @Override + public AnnotationVisitor visitAnnotationDefault() { + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + return super.visitAnnotationDefault(); + } + return null; + } + + @Override + public void visitParameter(String string, int i) { + if (expandTemplate(null) == TemplateExpander.Result.PASSED) { + super.visitParameter(string, i); + } } @Override diff --git a/src/share/classes/com/sun/btrace/util/templates/impl/MethodTimeStampExpander.java b/src/share/classes/com/sun/btrace/util/templates/impl/MethodTimeStampExpander.java index 8dbb3e0fe..3d535a8d2 100644 --- a/src/share/classes/com/sun/btrace/util/templates/impl/MethodTimeStampExpander.java +++ b/src/share/classes/com/sun/btrace/util/templates/impl/MethodTimeStampExpander.java @@ -27,7 +27,6 @@ import com.sun.btrace.util.templates.BTraceTemplates; import com.sun.btrace.util.templates.Template; -import java.util.concurrent.atomic.AtomicInteger; /** * A timestamp expander for method duration related templates @@ -53,4 +52,9 @@ public MethodTimeStampExpander(String className, END_TIME, DURATION); } + + @Override + protected void resetStartTime() { + // never reset the start time in the method body + } } diff --git a/src/share/classes/com/sun/btrace/util/templates/impl/TimeStampExpander.java b/src/share/classes/com/sun/btrace/util/templates/impl/TimeStampExpander.java index 0975994e9..c0357bf34 100644 --- a/src/share/classes/com/sun/btrace/util/templates/impl/TimeStampExpander.java +++ b/src/share/classes/com/sun/btrace/util/templates/impl/TimeStampExpander.java @@ -52,11 +52,6 @@ abstract public class TimeStampExpander implements TemplateExpander { private int startTimeIndex = -1; private boolean startTimeSet = false; - private int repCounter = 0; - private int startRunLen = 0; - private int endRunLen = 0; - private int durRunLen = 0; - private final Template startTimeTemplate; private final Template endTimeTemplate; private final Template durationTemplate; @@ -87,24 +82,19 @@ public Result expand(TemplateExpanderVisitor v, Template t) { try { if ((lastTemplate == null && t != null) || !lastTemplate.equals(t)) { if (durationTemplate.equals(lastTemplate)) { - durRunLen = repCounter; - repCounter = 0; v.expand(new Consumer() { public void consume(TemplateExpanderVisitor visitor) { - expandCallDuration(visitor, lastTemplate.getTags().contains("transient")); + expandCallDuration( + visitor, + true + ); } }); - startRunLen -= durRunLen; - if (startRunLen == 0) { - startTimeIndex = -1; - startTimeSet = false; - endTimeIndex = -1; - endTimeSet = false; - durationIndex = -1; - durationSet = false; - samplingInterval = Integer.MAX_VALUE; - } + resetStartTime(); + resetEndTime(); + resetDuration(); + samplingInterval = Integer.MAX_VALUE; return t != null ? Result.CONSUMED : Result.PASSED; } else if (startTimeTemplate.equals(lastTemplate)) { @@ -116,8 +106,6 @@ public void consume(TemplateExpanderVisitor visitor) { } } samplingInterval = Math.min(samplingInterval, sinter); - startRunLen = repCounter; - repCounter = 0; v.expand(new Consumer() { public void consume(TemplateExpanderVisitor visitor) { expandCallStartTime(visitor); @@ -125,8 +113,6 @@ public void consume(TemplateExpanderVisitor visitor) { }); return t != null ? Result.CONSUMED : Result.PASSED; } else if (endTimeTemplate.equals(lastTemplate)) { - endRunLen = repCounter; - repCounter = 0; v.expand(new Consumer() { public void consume(TemplateExpanderVisitor visitor) { expandCallEndTime(visitor); @@ -134,11 +120,9 @@ public void consume(TemplateExpanderVisitor visitor) { }); return t != null ? Result.CONSUMED : Result.PASSED; } else { - repCounter++; return Result.IGNORED; } } else { - repCounter++; return Result.IGNORED; } } finally { @@ -231,4 +215,18 @@ protected int getSamplingInterval() { protected String getMethodIdString(Template t) { return className + "#" + methodName + "#" + desc; } + + protected void resetDuration() { + durationIndex = -1; + durationSet = false; + } + + protected void resetEndTime() { + endTimeIndex = -1; + endTimeSet = false; + } + protected void resetStartTime() { + startTimeIndex = -1; + startTimeSet = false; + } } diff --git a/src/test/com/sun/btrace/runtime/ClinitInstrumentorTest.java b/src/test/com/sun/btrace/runtime/ClinitInstrumentorTest.java index 48f5ba7a9..779dae3b5 100644 --- a/src/test/com/sun/btrace/runtime/ClinitInstrumentorTest.java +++ b/src/test/com/sun/btrace/runtime/ClinitInstrumentorTest.java @@ -26,7 +26,12 @@ package com.sun.btrace.runtime; import com.sun.btrace.org.objectweb.asm.ClassReader; +import com.sun.btrace.org.objectweb.asm.ClassVisitor; import com.sun.btrace.org.objectweb.asm.ClassWriter; +import com.sun.btrace.org.objectweb.asm.MethodVisitor; +import com.sun.btrace.org.objectweb.asm.Opcodes; +import com.sun.btrace.util.LocalVariableHelperImpl; +import com.sun.btrace.util.templates.TemplateExpanderVisitor; import java.io.IOException; import java.lang.reflect.Field; import java.util.concurrent.atomic.AtomicLong; @@ -63,13 +68,31 @@ public void checkTransformedClinit() throws Exception { @Override protected void transform(String traceName) throws IOException { - Trace btrace = loadTrace(traceName); + final Trace btrace = loadTrace(traceName); ClassReader reader = new ClassReader(originalBC); ClassWriter writer = InstrumentUtils.newClassWriter(); InstrumentUtils.accept(reader, new ClinitInjector(writer, "btrace", btrace.className)); transformedBC = writer.toByteArray(); + + System.out.println(asmify(transformedBC)); + + ClassReader cr1 = new ClassReader(transformedBC); + ClassWriter cw1 = InstrumentUtils.newClassWriter(); + + InstrumentUtils.accept(reader, new ClassVisitor(Opcodes.ASM4, cw1) { + + @Override + public MethodVisitor visitMethod(int i, String string, String string1, String string2, String[] strings) { + MethodVisitor mv = super.visitMethod(i, string, string1, string2, strings); + LocalVariableHelperImpl lvh = new LocalVariableHelperImpl(mv, i, string1); + TemplateExpanderVisitor tev = new TemplateExpanderVisitor(lvh, btrace.className, string, string1); + return tev; + } + }); + + System.out.println(asmify(cw1.toByteArray())); System.err.println("==== " + traceName); } } diff --git a/src/test/com/sun/btrace/runtime/InstrumentorTest.java b/src/test/com/sun/btrace/runtime/InstrumentorTest.java index a1b561ccd..88809a8c6 100644 --- a/src/test/com/sun/btrace/runtime/InstrumentorTest.java +++ b/src/test/com/sun/btrace/runtime/InstrumentorTest.java @@ -102,7 +102,8 @@ public void methodEntryError() throws Exception { originalBC = loadTargetClass("OnMethodTest"); transform("onmethod/Error"); - checkTransformation("TRYCATCHBLOCK L0 L1 L1 java/lang/Throwable\nDUP\nASTORE 1\nALOAD 0\nLDC \"uncaught\"\nALOAD 1\n" + checkTransformation("TRYCATCHBLOCK L0 L1 L1 java/lang/Throwable\n" + + "DUP\nASTORE 1\nALOAD 0\nLDC \"uncaught\"\nALOAD 1\n" + "INVOKESTATIC resources/OnMethodTest.$btrace$traces$onmethod$Error$args (Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Throwable;)V"); } @@ -115,7 +116,7 @@ public void methodEntryErrorDuration() throws Exception { + "INVOKESTATIC java/lang/System.nanoTime ()J\nLSTORE 3\nDUP\nASTORE 5\nALOAD 0\nLDC \"uncaught\"\n" + "LLOAD 3\nLLOAD 1\nLSUB\nALOAD 5\n" + "INVOKESTATIC resources/OnMethodTest.$btrace$traces$onmethod$ErrorDuration$args (Ljava/lang/Object;Ljava/lang/String;JLjava/lang/Throwable;)V\n" - + "ATHROW\nMAXSTACK = 7\nMAXLOCALS = 6" + + "ATHROW" ); } @@ -153,7 +154,8 @@ public void methodEntrySyncEntry() throws Exception { originalBC = loadTargetClass("OnMethodTest"); transform("onmethod/SyncEntry"); - checkTransformation("TRYCATCHBLOCK L4 L5 L5 java/lang/Throwable\nDUP\nASTORE 2\nALOAD 0\nLDC \"sync\"\nALOAD 2\n" + checkTransformation("TRYCATCHBLOCK L4 L5 L5 java/lang/Throwable\nL6\n" + + "LINENUMBER 108 L6\nDUP\nASTORE 2\nALOAD 0\nLDC \"sync\"\nALOAD 2\n" + "INVOKESTATIC resources/OnMethodTest.$btrace$traces$onmethod$SyncEntry$args (Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V"); } @@ -162,7 +164,8 @@ public void methodEntrySyncExit() throws Exception { originalBC = loadTargetClass("OnMethodTest"); transform("onmethod/SyncExit"); - checkTransformation("TRYCATCHBLOCK L4 L5 L5 java/lang/Throwable\nL6\nLINENUMBER 110 L6\n" + checkTransformation("TRYCATCHBLOCK L4 L5 L5 java/lang/Throwable\nL6\n" + + "LINENUMBER 108 L6\nL7\nLINENUMBER 110 L7\n" + "DUP\nASTORE 2\nALOAD 0\nLDC \"resources/OnMethodTest\"\nALOAD 2\n" + "INVOKESTATIC resources/OnMethodTest.$btrace$traces$onmethod$SyncExit$args (Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V\n"); } @@ -312,22 +315,76 @@ public void methodEntryArgsDuration() throws Exception { checkTransformation("INVOKESTATIC java/lang/System.nanoTime ()J\nLSTORE 6\n" + "INVOKESTATIC java/lang/System.nanoTime ()J\nLSTORE 8\n" + "DUP2\nLSTORE 10\nALOAD 0\nLLOAD 10\nLLOAD 8\nLLOAD 6\nLSUB\n" - + "DUP2\nLSTORE 12\nALOAD 1\nLLOAD 2\nALOAD 4\nALOAD 5\n" + + "ALOAD 1\nLLOAD 2\nALOAD 4\nALOAD 5\n" + "INVOKESTATIC resources/OnMethodTest.$btrace$traces$onmethod$ArgsDuration$args (Ljava/lang/Object;JJLjava/lang/String;J[Ljava/lang/String;[I)V\n" + "MAXSTACK"); } + @Test + public void methodEntryArgsDurationMultiReturn() throws Exception { + originalBC = loadTargetClass("OnMethodTest"); + transform("onmethod/ArgsDurationMultiReturn"); + checkTransformation( + "INVOKESTATIC java/lang/System.nanoTime ()J\n" + + "LSTORE 6\n" + + "INVOKESTATIC java/lang/System.nanoTime ()J\n" + + "LSTORE 8\n" + + "DUP2\n" + + "LSTORE 10\n" + + "ALOAD 0\n" + + "LLOAD 10\n" + + "LLOAD 8\n" + + "LLOAD 6\n" + + "LSUB\n" + + "ALOAD 1\n" + + "LLOAD 2\n" + + "ALOAD 4\n" + + "ALOAD 5\n" + + "INVOKESTATIC resources/OnMethodTest.$btrace$traces$onmethod$ArgsDurationMultiReturn$args (Ljava/lang/Object;JJLjava/lang/String;J[Ljava/lang/String;[I)V\n" + + "INVOKESTATIC java/lang/System.nanoTime ()J\n" + + "LSTORE 12\n" + + "DUP2\n" + + "LSTORE 14\n" + + "ALOAD 0\n" + + "LLOAD 14\n" + + "LLOAD 12\n" + + "LLOAD 6\n" + + "LSUB\n" + + "ALOAD 1\n" + + "LLOAD 2\n" + + "ALOAD 4\n" + + "ALOAD 5\n" + + "INVOKESTATIC resources/OnMethodTest.$btrace$traces$onmethod$ArgsDurationMultiReturn$args (Ljava/lang/Object;JJLjava/lang/String;J[Ljava/lang/String;[I)V\n" + + "INVOKESTATIC java/lang/System.nanoTime ()J\n" + + "LSTORE 16\n" + + "DUP2\n" + + "LSTORE 18\n" + + "ALOAD 0\n" + + "LLOAD 18\n" + + "LLOAD 16\n" + + "LLOAD 6\n" + + "LSUB\n" + + "ALOAD 1\n" + + "LLOAD 2\n" + + "ALOAD 4\n" + + "ALOAD 5\n" + + "INVOKESTATIC resources/OnMethodTest.$btrace$traces$onmethod$ArgsDurationMultiReturn$args (Ljava/lang/Object;JJLjava/lang/String;J[Ljava/lang/String;[I)V\n" + + "MAXSTACK = 12\n" + + "MAXLOCALS = 20" + ); + } + @Test public void methodEntryArgsDurationSampled() throws Exception { originalBC = loadTargetClass("OnMethodTest"); transform("onmethod/ArgsDurationSampled"); checkTransformation( "LDC 0\nLSTORE 6\nLDC 20\nLDC 1\nINVOKESTATIC com/sun/btrace/util/SamplingSupport.sampleHit (II)Z\n" + - "DUP\nISTORE 8\nIFEQ L1\nINVOKESTATIC java/lang/System.nanoTime ()J\n" + - "LSTORE 6\nL1\nLDC 0\nLSTORE 9\nILOAD 8\nIFEQ L2\nINVOKESTATIC java/lang/System.nanoTime ()J\n" + - "LSTORE 9\nL2\nDUP2\nLSTORE 11\nALOAD 0\nLLOAD 11\n" + - "ILOAD 8\nIFEQ L3\nLLOAD 9\nLLOAD 6\nLSUB\nGOTO L4\n" + - "L3\nLDC 0\nL4\nDUP2\nLSTORE 13\n" + + "DUP\nISTORE 8\nIFEQ L0\nINVOKESTATIC java/lang/System.nanoTime ()J\n" + + "LSTORE 6\nLDC 0\nLSTORE 9\nILOAD 8\nIFEQ L1\nINVOKESTATIC java/lang/System.nanoTime ()J\n" + + "LSTORE 9\nL1\nDUP2\nLSTORE 11\nALOAD 0\nLLOAD 11\n" + + "ILOAD 8\nIFEQ L2\nLLOAD 9\nLLOAD 6\nLSUB\nGOTO L3\n" + + "L2\nLDC 0\nL3\n" + "ALOAD 1\nLLOAD 2\nALOAD 4\nALOAD 5\n" + "INVOKESTATIC resources/OnMethodTest.$btrace$traces$onmethod$ArgsDurationSampled$args (Ljava/lang/Object;JJLjava/lang/String;J[Ljava/lang/String;[I)V\n" ); @@ -346,7 +403,7 @@ public void methodEntryArgsDurationConstructor() throws Exception { transform("onmethod/ArgsDurationConstructor"); checkTransformation("INVOKESTATIC java/lang/System.nanoTime ()J\nLSTORE 2\n" + "INVOKESTATIC java/lang/System.nanoTime ()J\nLSTORE 4\n" - + "ALOAD 0\nLLOAD 4\nLLOAD 2\nLSUB\nDUP2\nLSTORE 6\nALOAD 1\n" + + "ALOAD 0\nLLOAD 4\nLLOAD 2\nLSUB\nALOAD 1\n" + "INVOKESTATIC resources/OnMethodTest.$btrace$traces$onmethod$ArgsDurationConstructor$args (Ljava/lang/Object;JLjava/lang/String;)V\n" + "MAXSTACK"); } @@ -359,10 +416,11 @@ public void methodEntryArgsDuration2() throws Exception { checkTransformation("INVOKESTATIC java/lang/System.nanoTime ()J\nLSTORE 6\n" + "INVOKESTATIC java/lang/System.nanoTime ()J\nLSTORE 8\n" + "DUP2\nLSTORE 10\nALOAD 0\nLLOAD 10\nLLOAD 8\nLLOAD 6\nLSUB\n" - + "DUP2\nLSTORE 12\nALOAD 1\nLLOAD 2\nALOAD 4\nALOAD 5\n" - + "INVOKESTATIC resources/OnMethodTest.$btrace$traces$onmethod$ArgsDuration2$args2 (Ljava/lang/Object;JJLjava/lang/String;J[Ljava/lang/String;[I)V\n" - + "DUP2\nLSTORE 14\nALOAD 0\nLLOAD 14\nLLOAD 12\n" + "ALOAD 1\nLLOAD 2\nALOAD 4\nALOAD 5\n" + + "INVOKESTATIC resources/OnMethodTest.$btrace$traces$onmethod$ArgsDuration2$args2 (Ljava/lang/Object;JJLjava/lang/String;J[Ljava/lang/String;[I)V\n" + + "INVOKESTATIC java/lang/System.nanoTime ()J\n" + + "LSTORE 12\nDUP2\nLSTORE 14\nALOAD 0\nLLOAD 14\n" + + "LLOAD 12\nLLOAD 6\nLSUB\nALOAD 1\nLLOAD 2\nALOAD 4\nALOAD 5\n" + "INVOKESTATIC resources/OnMethodTest.$btrace$traces$onmethod$ArgsDuration2$args (Ljava/lang/Object;JJLjava/lang/String;J[Ljava/lang/String;[I)V\n" + "MAXSTACK = 12\nMAXLOCALS = 16"); } @@ -374,17 +432,18 @@ public void methodEntryArgsDuration2Sampled() throws Exception { transform("onmethod/ArgsDuration2Sampled"); checkTransformation("LDC 0\nLSTORE 6\nLDC 20\nLDC 1\n" + "INVOKESTATIC com/sun/btrace/util/SamplingSupport.sampleHit (II)Z\n" - + "DUP\nISTORE 8\nIFEQ L1\n" + + "DUP\nISTORE 8\nIFEQ L0\n" + "INVOKESTATIC java/lang/System.nanoTime ()J\nLSTORE 6\n" - + "L1\nLDC 0\nLSTORE 9\nILOAD 8\nIFEQ L2\n" + + "LDC 0\nLSTORE 9\nILOAD 8\nIFEQ L1\n" + "INVOKESTATIC java/lang/System.nanoTime ()J\nLSTORE 9\n" - + "L2\nDUP2\nLSTORE 11\nALOAD 0\nLLOAD 11\n" - + "ILOAD 8\nIFEQ L3\nLLOAD 9\nLLOAD 6\nLSUB\nGOTO L4\n" - + "L3\nLDC 0\nL4\nDUP2\nLSTORE 13\n" + + "L1\nDUP2\nLSTORE 11\nALOAD 0\nLLOAD 11\n" + + "ILOAD 8\nIFEQ L2\nLLOAD 9\nLLOAD 6\nLSUB\nGOTO L3\n" + + "L2\nLDC 0\nL3\n" + "ALOAD 1\nLLOAD 2\nALOAD 4\nALOAD 5\n" + "INVOKESTATIC resources/OnMethodTest.$btrace$traces$onmethod$ArgsDuration2Sampled$args2 (Ljava/lang/Object;JJLjava/lang/String;J[Ljava/lang/String;[I)V\n" - + "DUP2\nLSTORE 15\nALOAD 0\nLLOAD 15\nLLOAD 13\n" - + "ALOAD 1\nLLOAD 2\nALOAD 4\nALOAD 5\n" + + "INVOKESTATIC java/lang/System.nanoTime ()J\n" + + "LSTORE 13\nDUP2\nLSTORE 15\nALOAD 0\nLLOAD 15\nLLOAD 13\n" + + "LLOAD 6\nLSUB\nALOAD 1\nLLOAD 2\nALOAD 4\nALOAD 5\n" + "INVOKESTATIC resources/OnMethodTest.$btrace$traces$onmethod$ArgsDuration2Sampled$args (Ljava/lang/Object;JJLjava/lang/String;J[Ljava/lang/String;[I)V\n"); } @@ -414,10 +473,13 @@ public void methodEntryArgsDurationConstructorErr() throws Exception { originalBC = loadTargetClass("OnMethodTest"); transform("onmethod/ArgsDurationConstructorErr"); checkTransformation("TRYCATCHBLOCK L0 L1 L1 java/lang/Throwable\n" - + "INVOKESTATIC java/lang/System.nanoTime ()J\nLSTORE 1\n" - + "INVOKESTATIC java/lang/System.nanoTime ()J\nLSTORE 3\n" - + "DUP\nASTORE 5\nALOAD 0\nLLOAD 3\nLLOAD 1\nLSUB\n" - + "ALOAD 5\n" + + "L2\n" + + "LINENUMBER 39 L2\n" + + "INVOKESTATIC java/lang/System.nanoTime ()J\n" + + "LSTORE 1\nL0\n" + + "INVOKESTATIC java/lang/System.nanoTime ()J\n" + + "LSTORE 3\nDUP\nASTORE 5\nALOAD 0\nLLOAD 3\n" + + "LLOAD 1\nLSUB\nALOAD 5\n" + "INVOKESTATIC resources/OnMethodTest.$btrace$traces$onmethod$ArgsDurationConstructorErr$args (Ljava/lang/Object;JLjava/lang/Throwable;)V\n" + "ATHROW"); } diff --git a/src/test/resources/OnMethodTest.java b/src/test/resources/OnMethodTest.java index c9cc93746..62583634b 100644 --- a/src/test/resources/OnMethodTest.java +++ b/src/test/resources/OnMethodTest.java @@ -30,7 +30,7 @@ import java.util.Map; /** - * + * !!! Only append the new methods; line numbers need to be kept intact !!! * @author Jaroslav Bachorik */ public class OnMethodTest { @@ -119,4 +119,18 @@ private long calLTargetX(String a, long b) { return 5L; } + public long argsMultiReturn(String a, long b, String[] c, int[] d) { + if (System.currentTimeMillis() > 325723059) { + return 0L; + } + + if (System.currentTimeMillis() > 32525) { + return 1L; + } + + { + System.out.println("fdsfg"); + return -1L; + } + } } diff --git a/src/test/support/InstrumentorTestBase.java b/src/test/support/InstrumentorTestBase.java index b7fd21da8..353f14107 100644 --- a/src/test/support/InstrumentorTestBase.java +++ b/src/test/support/InstrumentorTestBase.java @@ -41,12 +41,11 @@ import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Level; -import java.util.logging.Logger; import org.junit.After; import org.objectweb.asm.util.TraceClassVisitor; import static org.junit.Assert.*; import org.junit.Before; +import org.objectweb.asm.util.CheckClassAdapter; import sun.misc.Unsafe; /** @@ -119,6 +118,16 @@ protected void load() { } protected void checkTransformation(String expected) throws IOException { + org.objectweb.asm.ClassReader cr = new org.objectweb.asm.ClassReader(transformedBC); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + CheckClassAdapter.verify(cr, false, pw); + if (sw.toString().contains("AnalyzerException")) { + System.err.println(sw.toString()); + fail(); + } + String diff = diff(); System.err.println(diff); assertEquals(expected, diff.substring(0, diff.length() > expected.length() ? expected.length() : diff.length())); diff --git a/src/test/traces/onmethod/ArgsDurationMultiReturn.java b/src/test/traces/onmethod/ArgsDurationMultiReturn.java new file mode 100644 index 000000000..ea8711877 --- /dev/null +++ b/src/test/traces/onmethod/ArgsDurationMultiReturn.java @@ -0,0 +1,47 @@ +/* + * Copyright 2008-2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package traces.onmethod; + +import com.sun.btrace.annotations.BTrace; +import com.sun.btrace.annotations.Kind; +import com.sun.btrace.annotations.Location; +import com.sun.btrace.annotations.OnMethod; +import com.sun.btrace.annotations.Return; +import com.sun.btrace.annotations.Self; +import com.sun.btrace.annotations.Duration; +import static com.sun.btrace.BTraceUtils.*; + +/** + * + * @author Jaroslav Bachorik + */ +@BTrace +public class ArgsDurationMultiReturn { + @OnMethod(clazz="/.*\\.OnMethodTest/", method="argsMultiReturn", location=@Location(value=Kind.RETURN)) + public static void args(@Self Object self, @Return long retVal, @Duration long dur, String a, long b, String[] c, int[] d) { + println("args"); + } +} diff --git a/src/test/traces/onmethod/NoArgsEntryReturn.java b/src/test/traces/onmethod/NoArgsEntryReturn.java index 4f7a0dd32..ad3d9a9a2 100644 --- a/src/test/traces/onmethod/NoArgsEntryReturn.java +++ b/src/test/traces/onmethod/NoArgsEntryReturn.java @@ -47,5 +47,4 @@ public static void argsEmptyEntry(@Self Object x) { public static void argsEmptyReturn(@Self Object x) { println("return"); } - } diff --git a/test-lib/asm-5.0.2.jar b/test-lib/asm-5.0.2.jar deleted file mode 100644 index d3e6982c0..000000000 Binary files a/test-lib/asm-5.0.2.jar and /dev/null differ diff --git a/test-lib/asm-all-5.0.2.jar b/test-lib/asm-all-5.0.2.jar new file mode 100644 index 000000000..de769a8ed Binary files /dev/null and b/test-lib/asm-all-5.0.2.jar differ diff --git a/test-lib/asm-util-4.1.jar b/test-lib/asm-util-4.1.jar deleted file mode 100644 index 4d0777e48..000000000 Binary files a/test-lib/asm-util-4.1.jar and /dev/null differ diff --git a/test-lib/asm-util-5.0.2.jar b/test-lib/asm-util-5.0.2.jar deleted file mode 100644 index 9fc25abf4..000000000 Binary files a/test-lib/asm-util-5.0.2.jar and /dev/null differ