jpdadebugger.java
来自「JAVA Servlet2.3外文书籍源码」· Java 代码 · 共 244 行
JAVA
244 行
package debugging;
import com.sun.jdi.Bootstrap;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.StackFrame;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.VirtualMachine;
import com.sun.jdi.connect.AttachingConnector;
import com.sun.jdi.connect.Connector;
import com.sun.jdi.event.Event;
import com.sun.jdi.event.EventIterator;
import com.sun.jdi.event.EventQueue;
import com.sun.jdi.event.EventSet;
import com.sun.jdi.event.MethodEntryEvent;
import com.sun.jdi.request.EventRequestManager;
import com.sun.jdi.request.MethodEntryRequest;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Vector;
/**
* A class to trace method invocations in a remote VM
*/
public class JPDADebugger {
private static int SOCKET_ATTACH = 1;
private VirtualMachine vm = null;
private boolean running;
/**
* The main() method processes the command line arguments then calls
* execute().
*/
public static void main(String args[]) {
// Stores the address of the remote VM
String attachAddress = null;
// Stores the classes to watch
Vector includeClasses = new Vector();
// Handle the command line arguments
for (int i=0; i<args.length; i++) {
String thisArg = args[i];
if ("-attach".equals(thisArg.toLowerCase())) {
attachAddress=args[++i];
}
else if ("-include".equals(thisArg.toLowerCase())) {
String incString = args[++i];
StringTokenizer st = new StringTokenizer(incString, ":", false);
while (st.hasMoreTokens()) {
String thisOne = st.nextToken();
System.out.println("including " + thisOne);
includeClasses.addElement(thisOne);
}
}
}
// Create an instance of this class and try to execute it
JPDADebugger thisDebugger = new JPDADebugger();
try {
thisDebugger.execute(attachAddress,includeClasses);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* In this method we attach to the remote VM and go into a loop
* waiting for debug events.
*/
public void execute(String attachAddress, Vector includeClasses)
throws Exception {
if (includeClasses==null) {
includeClasses=new Vector();
}
// Initialize these to dummy values
String connectorName = null;
int connectType = -1;
String connectHost = null;
String connectPort = null;
// Get the host and port of the target VM
if (attachAddress!=null) {
connectorName = "com.sun.jdi.SocketAttach";
connectType = SOCKET_ATTACH;
int index = attachAddress.indexOf(":");
connectHost = attachAddress.substring(0, index);
connectPort = attachAddress.substring(index + 1);
} else {
throw new Exception ("ERROR: No attach address specified");
}
// Look for a suitable connector
Connector connector = null;
List connectors = Bootstrap.virtualMachineManager().allConnectors();
Iterator iter=connectors.iterator();
while (iter.hasNext()) {
Connector thisConnector=(Connector)iter.next();
if (thisConnector.name().equals(connectorName)) {
connector=thisConnector;
}
}
// If we didn't find one throw an exception
if (connector==null) {
throw new Exception ("ERROR: No connector with name " + connectorName);
}
// Set the host and port arguments of the connector
Map arguments=connector.defaultArguments();
Connector.Argument hostname = (Connector.Argument) arguments.get("hostname");
Connector.Argument port = (Connector.Argument) arguments.get("port");
hostname.setValue(connectHost);
port.setValue(connectPort);
// Cast the connector as AttachingConnector and try to attach
// to the remote VM
AttachingConnector attacher=(AttachingConnector) connector;
vm = null;
try {
vm=attacher.attach(arguments);
} catch (Exception e) {
e.printStackTrace();
throw new Exception ("ERROR: " + e + " @ attempting socket attach.");
}
// If we can't get hold of the remote VM throw an exception
if (vm==null) {
throw new Exception ("ERROR: No VM process connected.");
}
// Get the VM's EventRequestManager and add a MethodEntryRequest
// with a filter for each included class
EventRequestManager em = vm.eventRequestManager();
for (Enumeration e=includeClasses.elements(); e.hasMoreElements(); ) {
MethodEntryRequest meR=em.createMethodEntryRequest();
String pattern=(String) e.nextElement();
meR.addClassFilter(pattern);
meR.enable();
}
// Get hold of the VM event queue
EventQueue eventQ = vm.eventQueue();
// Loop continually, waiting for events
running = true;
while (running) {
// -- try to pop a set of events from the loop
EventSet eventSet = null;
try {
eventSet = eventQ.remove();
} catch (Exception e) {
System.err.println("ERROR: Interrupted Event Loop");
e.printStackTrace();
}
// Step through the events and proces each one
EventIterator eventIterator = eventSet.eventIterator();
while (eventIterator.hasNext()) {
Event event=eventIterator.nextEvent();
if (event instanceof MethodEntryEvent) {
processMethodEntryEvent((MethodEntryEvent)event);
}
}
// Tell the target VM to resume
vm.resume();
}
System.out.close();
}
/**
* This method is called for every MethodEntryEvent sent by the
* target VM.
*/
private void processMethodEntryEvent(MethodEntryEvent event) {
// What method was called?
String methodString = event.method().toString();
// What thread was it in ?
ThreadReference thread = event.thread();
// Get hold of the stack frames for this thread --
List stackList=null;
try {
stackList=thread.frames();
} catch (Exception e) {
return;
}
// Initiallize the caller and callee information
String calleeID = "?";
String calleeClass = "?";
String callerID = "?";
String callerClass = "?";
// Step through the stack frames
int level = 0;
for (Iterator it=stackList.iterator(); it.hasNext();) {
StackFrame stackFrame = (StackFrame) it.next();
ObjectReference thisObject = stackFrame.thisObject();
if (thisObject==null) {
continue;
}
if (level==0) {
calleeID=String.valueOf(thisObject.uniqueID());
String classString = thisObject.referenceType().toString();
StringTokenizer st = new StringTokenizer(classString, " ");
calleeClass = st.nextToken();
calleeClass = st.nextToken();
} else if (level==1) {
callerID = String.valueOf(thisObject.uniqueID());
String classString = thisObject.referenceType().toString();
StringTokenizer st = new StringTokenizer(classString, " ");
callerClass = st.nextToken();
callerClass = st.nextToken();
}
level++;
if (level > 1) {
break;
}
}
// Print the result with tags
System.out.println("<invocation><sender>" +
callerID+":"+callerClass +
"</sender><message>" +
methodString +
"</message><receiver>" +
calleeID + ":" +
calleeClass + "</receiver><thread>" +
thread.name() + "</thread></invocation>");
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?