|
Here is some software to make visualizations of Java code, using graphviz.
You can see me using it in class:
Other visualizers have been developed, including the work of Philip Guo and David Pritchard.
To install, you need
A related project is GraphvizBuilder.java (javadoc).
I use this to draw trees and graphs. For example:
public void toGraphviz(String filename) { GraphvizBuilder gb = new GraphvizBuilder (); toGraphviz (gb, null, root); gb.toFileUndirected (filename, "ordering=\"out\""); } private static void toGraphviz (GraphvizBuilder gb, Node parent, Node n) { if (n == null) { gb.addNullEdge (parent); return; } gb.addLabeledNode (n, Integer.toString (n.key)); if (parent != null) gb.addEdge (parent, n); toGraphviz (gb, n, n.left); toGraphviz (gb, n, n.right); }
will draw trees such as
For example, to draw every step of your running program, simply add the following two lines to the beginning of the main function.
Trace.run (); Trace.drawSteps ();
For example, if you run XFixedCapacityStack.java, you will get output like this:
and this:
Null references are not shown (configurable for objects via Trace.showNullFields
).
Here is a glossary for shapes:
Here is a glossary for arrows:
There are several ways to create drawings.
drawSteps()
will start drawing all steps of the program. See
main1
in XFixedCapacityStack.java for an example.drawStepsofMethod(String methodName)
will start drawing all steps
of the given method. drawStepsofMethods(String... methodName)
will start drawing all steps
of the given methods. For example, drawStepsofMethods("push", "pop")
.drawStepsEnd()
will stop drawing steps begun by any of the
preceding drawSteps
methods.
You can alternate calls to drawStepsEnd
and the
drawSteps
methods to dynamically select portions of the code.
The restrictions imposed by drawStepsofMethod
and
drawStepsofMethods
are erased by drawStepsEnd
.
Thus drawStepsEnd(); drawSteps()
will draw the steps of
all methods, regardless of prior calls to drawStepsofMethod
.drawSteps
methods, nothing will be drawn unless
you do so explicitly. You can do this by calling
Trace.draw()
. Whenever the debugger comes to a call to
Trace.draw()
, it creates a picture of the state.Trace.drawThisFrame()
will draw only the current stack
frame (and objects reachable from it).Trace.drawObjectsWithNames
.There are lots of options. See the javadoc for details.
Methods that begin with draw
may be called at any time.
But option methods must be called before Trace.run()
in
order to have any effect. Thus
is the same as
Trace.run(); Trace.showBuiltInObjects(true)
.
Correct usage is Trace.run()
.
Trace.showBuiltInObjects(true); Trace.run()
One useful option is Trace.setGraphizOutputDir(dirName)
,
which allows you to change where the drawings are place on your system.
By default they go on the user Desktop. You can specify an absolute or
relative path for dirName
. Relative paths are interpreted
with respect to the user home directory.
Another useful option is Trace.showBuiltInObjects(true)
,
which results in the following style of output:
The following results from Trace.showBuiltInObjectsVerbose(true);
The following results from
Trace.showObjectIdsRedundantly(true);
Here is a longer example: ZTraceExample.java
It produces output like this, which shows an exception being caught:
Here is a complete sequence of drawings: ZTraceExample-graphviz.pdf
It is also possible to get console output using
Trace.consoleShow(true)
or Trace.consoleShowVerbose(true)
:
ZTraceExample-console.txt