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:
*
* - They are exactly the same
- * - The left parameter is {@linkplain Object} or {@linkplain AnyType} and
+ *
- The left parameter is {@linkplain Object} or {@linkplain AnyType} and
* the right parameter is either {@linkplain Object} or an array
* - The left parameter is assignable from the right one (is a superclass of the right one)
*
@@ -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