|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
/* |
|
* This source code is provided to illustrate the usage of a given feature |
|
* or technique and has been deliberately simplified. Additional steps |
|
* required for a production-quality application, such as security checks, |
|
* input validation and proper error handling, might not be present in |
|
* this sample code. |
|
*/ |
|
|
|
|
|
package com.sun.tools.example.trace; |
|
|
|
import com.sun.jdi.VirtualMachine; |
|
import com.sun.jdi.Bootstrap; |
|
import com.sun.jdi.connect.*; |
|
|
|
import java.util.Map; |
|
import java.util.List; |
|
|
|
import java.io.PrintWriter; |
|
import java.io.FileWriter; |
|
import java.io.IOException; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public class Trace { |
|
|
|
|
|
private final VirtualMachine vm; |
|
|
|
|
|
private Thread errThread = null; |
|
|
|
|
|
private Thread outThread = null; |
|
|
|
|
|
private int debugTraceMode = 0; |
|
|
|
|
|
private boolean watchFields = false; |
|
|
|
|
|
private String[] excludes = {"java.*", "javax.*", "sun.*", |
|
"com.sun.*"}; |
|
|
|
|
|
|
|
*/ |
|
public static void main(String[] args) { |
|
new Trace(args); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
Trace(String[] args) { |
|
PrintWriter writer = new PrintWriter(System.out); |
|
int inx; |
|
for (inx = 0; inx < args.length; ++inx) { |
|
String arg = args[inx]; |
|
if (arg.charAt(0) != '-') { |
|
break; |
|
} |
|
if (arg.equals("-output")) { |
|
try { |
|
writer = new PrintWriter(new FileWriter(args[++inx])); |
|
} catch (IOException exc) { |
|
System.err.println("Cannot open output file: " + args[inx] |
|
+ " - " + exc); |
|
System.exit(1); |
|
} |
|
} else if (arg.equals("-all")) { |
|
excludes = new String[0]; |
|
} else if (arg.equals("-fields")) { |
|
watchFields = true; |
|
} else if (arg.equals("-dbgtrace")) { |
|
debugTraceMode = Integer.parseInt(args[++inx]); |
|
} else if (arg.equals("-help")) { |
|
usage(); |
|
System.exit(0); |
|
} else { |
|
System.err.println("No option: " + arg); |
|
usage(); |
|
System.exit(1); |
|
} |
|
} |
|
if (inx >= args.length) { |
|
System.err.println("<class> missing"); |
|
usage(); |
|
System.exit(1); |
|
} |
|
StringBuffer sb = new StringBuffer(); |
|
sb.append(args[inx]); |
|
for (++inx; inx < args.length; ++inx) { |
|
sb.append(' '); |
|
sb.append(args[inx]); |
|
} |
|
vm = launchTarget(sb.toString()); |
|
generateTrace(writer); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
void generateTrace(PrintWriter writer) { |
|
vm.setDebugTraceMode(debugTraceMode); |
|
EventThread eventThread = new EventThread(vm, excludes, writer); |
|
eventThread.setEventRequests(watchFields); |
|
eventThread.start(); |
|
redirectOutput(); |
|
vm.resume(); |
|
|
|
|
|
try { |
|
eventThread.join(); |
|
errThread.join(); |
|
outThread.join(); |
|
} catch (InterruptedException exc) { |
|
// we don't interrupt |
|
} |
|
writer.close(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
VirtualMachine launchTarget(String mainArgs) { |
|
LaunchingConnector connector = findLaunchingConnector(); |
|
Map<String, Connector.Argument> arguments = |
|
connectorArguments(connector, mainArgs); |
|
try { |
|
return connector.launch(arguments); |
|
} catch (IOException exc) { |
|
throw new Error("Unable to launch target VM: " + exc); |
|
} catch (IllegalConnectorArgumentsException exc) { |
|
throw new Error("Internal error: " + exc); |
|
} catch (VMStartException exc) { |
|
throw new Error("Target VM failed to initialize: " + |
|
exc.getMessage()); |
|
} |
|
} |
|
|
|
void redirectOutput() { |
|
Process process = vm.process(); |
|
|
|
|
|
errThread = new StreamRedirectThread("error reader", |
|
process.getErrorStream(), |
|
System.err); |
|
outThread = new StreamRedirectThread("output reader", |
|
process.getInputStream(), |
|
System.out); |
|
errThread.start(); |
|
outThread.start(); |
|
} |
|
|
|
|
|
|
|
*/ |
|
LaunchingConnector findLaunchingConnector() { |
|
List<Connector> connectors = Bootstrap.virtualMachineManager().allConnectors(); |
|
for (Connector connector : connectors) { |
|
if (connector.name().equals("com.sun.jdi.CommandLineLaunch")) { |
|
return (LaunchingConnector)connector; |
|
} |
|
} |
|
throw new Error("No launching connector"); |
|
} |
|
|
|
|
|
|
|
*/ |
|
Map<String, Connector.Argument> connectorArguments(LaunchingConnector connector, String mainArgs) { |
|
Map<String, Connector.Argument> arguments = connector.defaultArguments(); |
|
Connector.Argument mainArg = |
|
(Connector.Argument)arguments.get("main"); |
|
if (mainArg == null) { |
|
throw new Error("Bad launching connector"); |
|
} |
|
mainArg.setValue(mainArgs); |
|
|
|
if (watchFields) { |
|
|
|
Connector.Argument optionArg = |
|
(Connector.Argument)arguments.get("options"); |
|
if (optionArg == null) { |
|
throw new Error("Bad launching connector"); |
|
} |
|
optionArg.setValue("-classic"); |
|
} |
|
return arguments; |
|
} |
|
|
|
|
|
|
|
*/ |
|
void usage() { |
|
System.err.println("Usage: java Trace <options> <class> <args>"); |
|
System.err.println("<options> are:"); |
|
System.err.println( |
|
" -output <filename> Output trace to <filename>"); |
|
System.err.println( |
|
" -all Include system classes in output"); |
|
System.err.println( |
|
" -help Print this help message"); |
|
System.err.println("<class> is the program to trace"); |
|
System.err.println("<args> are the arguments to <class>"); |
|
} |
|
} |