- Fix agentsettings parse bug

- Fix method entry source line capture
- Activate callers tab when data is collected
- Add debug test
This commit is contained in:
Martin Hare Robertson 2010-04-10 21:28:09 +01:00
parent a2a92d3814
commit fe147f6a11
19 changed files with 115 additions and 342 deletions

View File

@ -3,5 +3,6 @@
<classpathentry kind="src" path="src"/>
<classpathentry kind="lib" path="lib/traceagent.jar" sourcepath="/org.intrace"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="C:/Program Files/Java/jdk1.6.0/lib/tools.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

Binary file not shown.

View File

@ -1,10 +0,0 @@
package org.intrace.agent;
public class AgentConfigConstants
{
public static final String CLASS_REGEX = "AGENT_CLASS_REGEX";
public static final String TRACING_ENABLED = "AGENT_TRACING_ENABLED";
public static final String SAVE_TRACED_CLASSFILES = "AGENT_SAVE_TRACED_CLASSFILES";
public static final String VERBOSE_MODE = "AGENT_VERBOSE_MODE";
public static final String ALLOW_JARS_TO_BE_TRACED = "AGENT_LLOW_JARS_TO_BE_TRACED";
}

View File

@ -23,7 +23,7 @@ public class AgentSettings
public AgentSettings(String args)
{
parseArg(args);
parseArgs(args);
}
public AgentSettings(AgentSettings oldInstance)

View File

@ -16,23 +16,31 @@ import org.objectweb.asm.commons.EmptyVisitor;
*/
public class ClassBranchLineAnalysis extends EmptyVisitor
{
private Map<String, Set<Integer>> methodBranchTraceLines = new HashMap<String, Set<Integer>>();
public final Map<String, Set<Integer>> methodBranchTraceLines = new HashMap<String, Set<Integer>>();
public final Map<String, Integer> methodEntryLine = new HashMap<String, Integer>();
private Set<Integer> branchTraceLines = new HashSet<Integer>();
private Map<Label,Integer> methodLabelLineNos = new HashMap<Label,Integer>();
private final Map<Label,Integer> methodLabelLineNos = new HashMap<Label,Integer>();
private String methodSig;
private boolean traceThisLine = false;
private boolean recordedMethodEntryLine = false;
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
{
methodLabelLineNos.clear();
methodSig = name + desc;
recordedMethodEntryLine = false;
return this;
}
@Override
public void visitLineNumber(int xiLineNo, Label xiLabel)
{
if (!recordedMethodEntryLine)
{
methodEntryLine.put(methodSig, xiLineNo);
recordedMethodEntryLine = true;
}
methodLabelLineNos.put(xiLabel, xiLineNo);
if (traceThisLine)
{
@ -68,12 +76,4 @@ public class ClassBranchLineAnalysis extends EmptyVisitor
branchTraceLines = new HashSet<Integer>();
}
}
/**
* @return Analysis data.
*/
public Map<String, Set<Integer>> getMethodBranchLabels()
{
return methodBranchTraceLines;
}
}

View File

@ -102,7 +102,7 @@ public class ClassTransformer implements ClassFileTransformer
{
inst.retransformClasses(loadedClass);
}
catch (UnmodifiableClassException e)
catch (Exception e)
{
// Write exception to stdout
e.printStackTrace();
@ -139,7 +139,7 @@ public class ClassTransformer implements ClassFileTransformer
ProtectionDomain protectionDomain)
{
// Don't modify self
if (className.startsWith("gb.instrument"))
if (className.startsWith("org.intrace"))
{
if (args.isVerboseMode())
{
@ -262,7 +262,7 @@ public class ClassTransformer implements ClassFileTransformer
cr.accept(analysis, false);
InstrumentedClassWriter writer = new InstrumentedClassWriter(xiClassName,
cr,
analysis.getMethodBranchLabels());
analysis);
cr.accept(writer, false);
return writer.toByteArray();
}

View File

@ -1,7 +1,6 @@
package org.intrace.agent;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.objectweb.asm.ClassReader;
@ -14,35 +13,36 @@ import org.objectweb.asm.MethodVisitor;
public class InstrumentedClassWriter extends ClassWriter
{
private final String mClassName;
private final Map<String, Set<Integer>> methodBranchTraceLines;
private final ClassBranchLineAnalysis analysis;
/**
* cTor
*
* @param xiClassName
* @param xiReader
* @param xiMap
* @param analysis
*/
public InstrumentedClassWriter(String xiClassName, ClassReader xiReader,
Map<String, Set<Integer>> xiMap)
ClassBranchLineAnalysis xiAnalysis)
{
super(xiReader, true);
mClassName = xiClassName;
methodBranchTraceLines = xiMap;
analysis = xiAnalysis;
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions)
String signature, String[] exceptions)
{
MethodVisitor mv = super.visitMethod(access, name, desc, signature,
exceptions);
Set<Integer> branchTraceLines = methodBranchTraceLines.get(name + desc);
exceptions);
Set<Integer> branchTraceLines = analysis.methodBranchTraceLines.get(name + desc);
Integer entryLine = analysis.methodEntryLine.get(name + desc);
if (branchTraceLines == null)
{
branchTraceLines = new HashSet<Integer>();
}
return new InstrumentedMethodWriter(mv, mClassName, name, desc, branchTraceLines);
return new InstrumentedMethodWriter(mv, mClassName, name, desc, branchTraceLines, entryLine);
}
}

View File

@ -23,6 +23,7 @@ public class InstrumentedMethodWriter extends MethodAdapter
private int lineNumber = -1;
private final Set<Integer> branchTraceLines;
private final Integer entryLine;
private boolean writeTraceLine = false;
@ -31,47 +32,50 @@ public class InstrumentedMethodWriter extends MethodAdapter
* @param xiMethodVisitor
* @param xiClassName
* @param xiMethodName
* @param xiDesc
* @param xiDesc
* @param xiBranchTraceLines
* @param entryLine
*/
public InstrumentedMethodWriter(MethodVisitor xiMethodVisitor,
String xiClassName,
String xiMethodName,
String xiDesc,
Set<Integer> xiBranchTraceLines)
String xiClassName,
String xiMethodName,
String xiDesc,
Set<Integer> xiBranchTraceLines,
Integer xiEntryLine)
{
super(xiMethodVisitor);
className = xiClassName;
methodName = xiMethodName;
methodDescriptor = xiDesc;
branchTraceLines = xiBranchTraceLines;
entryLine = xiEntryLine;
}
@Override
public void visitCode()
{
generateCallToWriteBranchTrace(TraceType.BEGIN,-1);
generateCallToWriteBranchTrace(TraceType.BEGIN,((entryLine != null ? entryLine : -1)));
traceArgs();
super.visitCode();
}
private void traceArgs()
{
Type[] argTypes = Type.getArgumentTypes(methodDescriptor);
for (int ii = 0; ii < argTypes.length; ii++)
{
String typeDescriptor = argTypes[ii].getDescriptor();
String typeDescriptor = argTypes[ii].getDescriptor();
if (argTypes[ii].getSort() == Type.OBJECT)
{
typeDescriptor = "Ljava/lang/Object;";
}
else if ((argTypes[ii].getSort() == Type.ARRAY) &&
(argTypes[ii].getDescriptor().startsWith("[L")))
(argTypes[ii].getDescriptor().startsWith("[L")))
{
typeDescriptor = "[Ljava/lang/Object;";
}
mv.visitLdcInsn(className);
mv.visitLdcInsn(methodName);
mv.visitVarInsn(Opcodes.ALOAD, ii);
@ -79,12 +83,12 @@ public class InstrumentedMethodWriter extends MethodAdapter
HELPER_CLASS,
"arg",
"(Ljava/lang/String;Ljava/lang/String;" + typeDescriptor + ")V");
}
}
}
@Override
public void visitLineNumber(int xiLineNumber, Label label)
{
{
lineNumber = xiLineNumber;
if (writeTraceLine ||
branchTraceLines.contains(xiLineNumber))
@ -120,41 +124,42 @@ public class InstrumentedMethodWriter extends MethodAdapter
{
switch (traceType)
{
case BEGIN:
{
mv.visitLdcInsn(className);
mv.visitLdcInsn(methodName);
mv.visitMethodInsn(INVOKESTATIC,
HELPER_CLASS,
"enter",
"(Ljava/lang/String;Ljava/lang/String;)V");
}
break;
case BRANCH:
{
mv.visitLdcInsn(className);
mv.visitLdcInsn(methodName);
mv.visitIntInsn(Opcodes.BIPUSH, lineNumber);
mv.visitMethodInsn(INVOKESTATIC,
HELPER_CLASS,
"branch",
"(Ljava/lang/String;Ljava/lang/String;I)V");
}
break;
case END:
{
mv.visitLdcInsn(className);
mv.visitLdcInsn(methodName);
mv.visitIntInsn(Opcodes.BIPUSH, lineNumber);
mv.visitMethodInsn(INVOKESTATIC,
HELPER_CLASS,
"exit",
"(Ljava/lang/String;Ljava/lang/String;I)V");
}
break;
}
case BEGIN:
{
mv.visitLdcInsn(className);
mv.visitLdcInsn(methodName);
mv.visitIntInsn(Opcodes.BIPUSH, lineNumber);
mv.visitMethodInsn(INVOKESTATIC,
HELPER_CLASS,
"enter",
"(Ljava/lang/String;Ljava/lang/String;I)V");
}
break;
case BRANCH:
{
mv.visitLdcInsn(className);
mv.visitLdcInsn(methodName);
mv.visitIntInsn(Opcodes.BIPUSH, lineNumber);
mv.visitMethodInsn(INVOKESTATIC,
HELPER_CLASS,
"branch",
"(Ljava/lang/String;Ljava/lang/String;I)V");
}
break;
case END:
{
mv.visitLdcInsn(className);
mv.visitLdcInsn(methodName);
mv.visitIntInsn(Opcodes.BIPUSH, lineNumber);
mv.visitMethodInsn(INVOKESTATIC,
HELPER_CLASS,
"exit",
"(Ljava/lang/String;Ljava/lang/String;I)V");
}
break;
}
}
private enum TraceType

View File

@ -37,7 +37,7 @@ public class AgentClientConnection implements Runnable
serverRef = agentServer;
connectedClient = xiConnectedClient;
transformer = xiTransformer;
System.out.println("Connected to: " + xiConnectedClient.getPort());
System.out.println("## Connected to: " + xiConnectedClient.getPort());
}
@Override
@ -79,7 +79,7 @@ public class AgentClientConnection implements Runnable
quit = true;
}
}
System.out.println("Disconnected from: " + connectedClient.getPort());
System.out.println("## Disconnected from: " + connectedClient.getPort());
connectedClient.close();
}
catch (IOException e1)

View File

@ -16,7 +16,7 @@ import org.intrace.agent.ClassTransformer;
public class AgentServer implements Runnable
{
private final ClassTransformer transformer;
private final Map<AgentClientConnection, Object> clientConnections = new ConcurrentHashMap<AgentClientConnection, Object>();
/**
@ -32,7 +32,7 @@ public class AgentServer implements Runnable
{
clientConnections.remove(connection);
}
public void broadcastMessage(AgentClientConnection requestingConn, Object message) throws IOException
{
IOException ex = null;
@ -47,7 +47,7 @@ public class AgentServer implements Runnable
if (requestingConn == clientConn)
{
ex = ioex;
}
}
}
}
if (ex != null)
@ -55,7 +55,7 @@ public class AgentServer implements Runnable
throw ex;
}
}
@Override
public void run()
{
@ -67,7 +67,7 @@ public class AgentServer implements Runnable
try
{
ServerSocket serversock = new ServerSocket(tracePort);
System.out.println("Listening on port " + serversock.getLocalPort());
System.out.println("## Listening on port " + serversock.getLocalPort());
while (true)
{
Socket connectedClient = serversock.accept();
@ -77,13 +77,13 @@ public class AgentServer implements Runnable
clientThread.setDaemon(true);
clientThread.setName("AgentServer-Client" + clientNum);
clientThread.start();
clientNum++;
clientNum++;
}
}
catch (BindException e)
{
numAllowedExcept--;
System.out.println("Unable to listen on port: " + tracePort);
System.out.println("## Unable to listen on port: " + tracePort);
tracePort++;
}
catch (Throwable t)
@ -100,6 +100,6 @@ public class AgentServer implements Runnable
}
}
}
System.out.println("Too many exceptions - server thread quitting.");
System.out.println("## Too many exceptions - server thread quitting.");
}
}

View File

@ -1,81 +0,0 @@
package org.intrace.client.gui;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
public class RegexInput
{
private Shell sShell = null; // @jve:decl-index=0:visual-constraint="10,10"
private Text regexInput = null;
private Button setRegexButton = null;
private Button cancelButton = null;
private TraceWindow instanceRef = null; // @jve:decl-index=0:
/**
* This method initializes sShell
*/
private void createSShell()
{
GridData gridData2 = new GridData();
gridData2.widthHint = 100;
gridData2.horizontalAlignment = org.eclipse.swt.layout.GridData.CENTER;
GridData gridData1 = new GridData();
gridData1.widthHint = 100;
gridData1.horizontalAlignment = org.eclipse.swt.layout.GridData.CENTER;
GridData gridData = new GridData();
gridData.horizontalSpan = 2;
gridData.widthHint = 300;
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 2;
gridLayout.makeColumnsEqualWidth = true;
sShell = new Shell(SWT.APPLICATION_MODAL | SWT.CLOSE | SWT.TITLE | SWT.MIN);
sShell.setText("Enter Regex");
sShell.setLayout(gridLayout);
sShell.setSize(new Point(326, 82));
sShell.addShellListener(new org.eclipse.swt.events.ShellAdapter()
{
public void shellClosed(org.eclipse.swt.events.ShellEvent e)
{
sShell.dispose();
}
});
regexInput = new Text(sShell, SWT.BORDER);
regexInput.setLayoutData(gridData);
setRegexButton = new Button(sShell, SWT.NONE);
setRegexButton.setText("Set Class Regex");
setRegexButton.setLayoutData(gridData1);
setRegexButton.addMouseListener(new org.eclipse.swt.events.MouseAdapter()
{
public void mouseUp(org.eclipse.swt.events.MouseEvent e)
{
instanceRef.setRegex(regexInput.getText());
sShell.close();
}
});
cancelButton = new Button(sShell, SWT.NONE);
cancelButton.setText("Cancel");
cancelButton.setLayoutData(gridData2);
cancelButton.addMouseListener(new org.eclipse.swt.events.MouseAdapter()
{
public void mouseUp(org.eclipse.swt.events.MouseEvent e)
{
sShell.close();
}
});
}
public void open(TraceWindow instanceWindowRef, String initText)
{
createSShell();
sShell.open();
regexInput.setText(initText);
instanceRef = instanceWindowRef;
}
}

View File

@ -513,6 +513,7 @@ public class TraceWindow
{
callersTree.removeAll();
addCallersData(callersTree, callersMap);
outputTabFolder.setSelection(callersOutputTabItem);
}
});
}

View File

@ -1,60 +0,0 @@
package org.intrace.client.gui.helper;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import org.intrace.client.gui.TraceWindow;
public class NetworkTraceReceiverThread implements Runnable
{
private final Socket traceSocket;
private final TraceWindow window;
public NetworkTraceReceiverThread(InetAddress address, int networkTracePort, TraceWindow window) throws IOException
{
this.window = window;
traceSocket = new Socket();
traceSocket.connect(new InetSocketAddress(address, networkTracePort));
}
public void start()
{
Thread t = new Thread(this);
t.setDaemon(true);
t.setName("Network Trace Receiver");
t.start();
}
@Override
public void run()
{
try
{
ObjectInputStream objIn = new ObjectInputStream(traceSocket.getInputStream());
while (true)
{
String traceLine = (String)objIn.readObject();
window.addMessage(traceLine);
}
}
catch (Exception e)
{
disconnect();
}
}
public void disconnect()
{
try
{
traceSocket.close();
}
catch (IOException e)
{
// Do nothing
}
}
}

View File

@ -173,11 +173,11 @@ public class AgentHelper
* STATIC IMPLEMENTATION OF IOutput
*/
public static void enter(String className, String methodName)
public static void enter(String className, String methodName, int lineNo)
{
for (IOutput outputHandler : outputHandlers.keySet())
{
outputHandler.enter(className, methodName);
outputHandler.enter(className, methodName, lineNo);
}
}

View File

@ -7,7 +7,7 @@ import java.util.Map;
*/
public interface IOutput
{
public void enter(String className, String methodName);
public void enter(String className, String methodName, int lineNo);
public void arg(String className, String methodName, byte byteArg);
public void arg(String className, String methodName, byte[] byteArrayArg);

View File

@ -121,7 +121,7 @@ public class IOutputAdapter implements IOutput
}
@Override
public void enter(String className, String methodName)
public void enter(String className, String methodName, int lineNo)
{
// Do nothing
}

View File

@ -43,17 +43,17 @@ public class CallersOutput extends IOutputAdapter
}
@Override
public void enter(String className, String methodName)
public void enter(String className, String methodName, int lineNo)
{
if (callersSettings.isCallersEnabled()
&& callersSettings.getMethodRegex().matcher(methodName).matches())
{
recordCall();
recordCall(lineNo);
}
}
@SuppressWarnings("unchecked")
private synchronized void recordCall()
private synchronized void recordCall(int lineNo)
{
StackTraceElement[] stackTrace = new Exception().getStackTrace();
if ((stackTrace != null) && (stackTrace.length > 3))
@ -64,7 +64,9 @@ public class CallersOutput extends IOutputAdapter
StackTraceElement element = stackTrace[ii];
String stackLine = element.getClassName() + "#"
+ element.getMethodName() + ":"
+ ((element.getLineNumber() > -1) ? element.getLineNumber() : "unknown") ;
+ ((element.getLineNumber() > -1) ?
element.getLineNumber() :
((lineNo > -1) ? lineNo : "unknown"));
Object treeElementObj = treeElement.get(stackLine);
if (treeElementObj == null)

View File

@ -1,85 +0,0 @@
package org.intrace.output.trace;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class NetworkTraceSenderThread implements Runnable
{
private final ServerSocket networkSocket;
private final BlockingQueue<String> outgoingTrace = new LinkedBlockingQueue<String>(100);
private Set<NetworkTraceSenderThread> set;
public NetworkTraceSenderThread(ServerSocket networkSocket)
{
this.networkSocket = networkSocket;
}
public void start(Set<NetworkTraceSenderThread> set)
{
this.set = set;
Thread networkThread = new Thread(this);
networkThread.setDaemon(true);
networkThread.setName("Network Trace Sender");
networkThread.start();
}
private void stop()
{
try
{
networkSocket.close();
}
catch (IOException e)
{
// Throw away
}
set.remove(this);
System.out.println("## Network Trace Disconnected");
}
public void queueTrace(String traceLine)
{
try
{
outgoingTrace.put(traceLine);
}
catch (InterruptedException e)
{
// Throw away
}
}
@Override
public void run()
{
Socket traceSendingSocket;
try
{
traceSendingSocket = networkSocket.accept();
try
{
ObjectOutputStream traceWriter = new ObjectOutputStream(traceSendingSocket.getOutputStream());
while (true)
{
String traceLine = outgoingTrace.take();
traceWriter.writeObject(traceLine);
}
}
catch (Exception e)
{
traceSendingSocket.close();
throw e;
}
}
catch (Exception e1)
{
stop();
}
}
}

View File

@ -17,31 +17,31 @@ public class TraceOutput implements IOutput
private boolean argTrace = false;
final TraceSettings traceSettings = new TraceSettings("");
public String getResponse(String args)
{
TraceSettings oldSettings = new TraceSettings(traceSettings);
traceSettings.parseArgs(args);
if ((oldSettings.isEntryExitTraceEnabled() != traceSettings.isEntryExitTraceEnabled()) ||
(oldSettings.isBranchTraceEnabled() != traceSettings.isBranchTraceEnabled()) ||
(oldSettings.isArgTraceEnabled() != traceSettings.isArgTraceEnabled()))
{
System.out.println("## Trace Settings Changed");
}
entryExitTrace = traceSettings.isEntryExitTraceEnabled();
branchTrace = traceSettings.isBranchTraceEnabled();
argTrace = traceSettings.isArgTraceEnabled();
return null;
}
public Map<String,String> getSettingsMap()
{
return traceSettings.getSettingsMap();
}
@Override
public void arg(String className, String methodName, byte byteArg)
{
@ -56,7 +56,7 @@ public class TraceOutput implements IOutput
if (argTrace)
{
AgentHelper.writeOutput(className + ":" + methodName + ": Arg: "
+ Arrays.toString(byteArrayArg));
+ Arrays.toString(byteArrayArg));
}
}
@ -74,7 +74,7 @@ public class TraceOutput implements IOutput
if (argTrace)
{
AgentHelper.writeOutput(className + ":" + methodName + ": Arg: "
+ Arrays.toString(shortArrayArg));
+ Arrays.toString(shortArrayArg));
}
}
@ -93,7 +93,7 @@ public class TraceOutput implements IOutput
if (argTrace)
{
AgentHelper.writeOutput(className + ":" + methodName + ": Arg: "
+ Arrays.toString(intArrayArg));
+ Arrays.toString(intArrayArg));
}
}
@ -112,7 +112,7 @@ public class TraceOutput implements IOutput
if (argTrace)
{
AgentHelper.writeOutput(className + ":" + methodName + ": Arg: "
+ Arrays.toString(longArrayArg));
+ Arrays.toString(longArrayArg));
}
}
@ -131,7 +131,7 @@ public class TraceOutput implements IOutput
if (argTrace)
{
AgentHelper.writeOutput(className + ":" + methodName + ": Arg: "
+ Arrays.toString(floatArrayArg));
+ Arrays.toString(floatArrayArg));
}
}
@ -150,7 +150,7 @@ public class TraceOutput implements IOutput
if (argTrace)
{
AgentHelper.writeOutput(className + ":" + methodName + ": Arg: "
+ Arrays.toString(doubleArrayArg));
+ Arrays.toString(doubleArrayArg));
}
}
@ -169,7 +169,7 @@ public class TraceOutput implements IOutput
if (argTrace)
{
AgentHelper.writeOutput(className + ":" + methodName + ": Arg: "
+ Arrays.toString(boolArrayArg));
+ Arrays.toString(boolArrayArg));
}
}
@ -188,7 +188,7 @@ public class TraceOutput implements IOutput
if (argTrace)
{
AgentHelper.writeOutput(className + ":" + methodName + ": Arg: "
+ Arrays.toString(charArrayArg));
+ Arrays.toString(charArrayArg));
}
}
@ -206,7 +206,7 @@ public class TraceOutput implements IOutput
if (argTrace)
{
AgentHelper.writeOutput(className + ":" + methodName + ": Arg: "
+ Arrays.toString(objArrayArg));
+ Arrays.toString(objArrayArg));
}
}
@ -220,11 +220,11 @@ public class TraceOutput implements IOutput
}
@Override
public void enter(String className, String methodName)
public void enter(String className, String methodName, int lineNo)
{
if (entryExitTrace)
{
AgentHelper.writeOutput(className + ":" + methodName + ": {");
AgentHelper.writeOutput(className + ":" + methodName + ": {:" + lineNo);
}
}