Python Tutor is a free tool that has been used by tens of millions of people since 2010 to visualize and debug code step-by-step. Despite its name, it also works for Java. If you teach AP Computer Science A, here is this article's core argument: the official Course and Exam Description (CED) repeatedly directs students to hand-trace code, and Python Tutor is an automatic code tracer – so it can serve as an unlimited supply of worked examples for students to check their hand-traces against.
The CED's emphasis on hand-tracing is everywhere once you look for it. Its instructional guidance suggests that students trace code on paper with sample inputs before typing it in, keep trace tables with a column for each variable, "draw a memory diagram that shows references and the arrays they point to," and "create a call tree or a stack trace" for recursive methods. There's a good reason for that emphasis: Analyze Code questions – determine the result or output of given program code – make up the largest share of the multiple-choice section (37–53% by the CED's own weighting). Python Tutor draws those same diagrams automatically for any code that you or your students type in. Since students must still trace by hand on the exam, the visualizer isn't a substitute for that skill: a student traces on paper first, then steps through the visualization to check their work at every step, seeing exactly where their mental model went wrong.
If you think this may be helpful for your students, please share this direct link in relevant course materials, chat groups, mailing lists, or discussion forums:
The rest of this article walks through the four units of the current course framework (which was reorganized for the 2025-26 school year) and shows what the visualizer can (and can't) illustrate in each one. All of the examples below are live: drag the slider under each one to step forward and back through execution, and click "Edit Code" under any example to open it in the full Python Tutor editor, where you and your students can modify and re-run it. Several examples are adapted from the sample exam questions published in the CED, so they may look familiar.
(One small detail you may appreciate: the CED recommends turning off IDE autocompletion because students must hand-write code on the exam. Python Tutor's editor has no autocompletion, so students type every character themselves.)
Credits: The original Java visualizer was created in 2013 by David Pritchard and Will Gwozdz. My earlier companion article, How the Python Tutor visualizer can help students in your Java programming courses, covers general Java features such as inheritance and polymorphism; the article you're reading now focuses specifically on what's in the AP CS A framework.
This unit (15–25% of the exam) starts with primitive types,
expressions, and calling Math and String methods, then hits the first
big conceptual wall of the course: objects and references. The CED
describes a reference as something that "can be thought of as the
memory address of that object," which is easy to say and hard for
students to picture. Python Tutor pictures it directly: primitive
values (int, double, boolean) appear inline inside stack frames,
while objects appear in a separate heap area with arrows pointing to
them.
In this example, small and big each point to their own Circle
object, and alias points to the same object as big – two
arrows, one object. Step through the constructor calls near the
beginning and you can watch each field hold its default value (0.0)
for a moment before the constructor body assigns it. In the current
step (Step 12), the grow method is running: its frame holds the
parameter amount plus a this reference pointing to the same object
that big and alias point to. Since there's only one object, growing
it through alias also changes what big.getRadius() returns later.
Aliasing quietly underlies many exam questions about object references,
and here it's simply visible: two arrows pointing at one box.
Strings get an entire topic (1.15) and show up every year in the free-response section, so here is a small example adapted from a sample multiple-choice question in the CED:
Students can watch str2 get built up by substring calls while
str1 never changes, since Strings are immutable and every String
method returns a new string. (By default the visualizer displays
strings inline to reduce clutter; on the live site you can select
"show Strings and wrappers as objects" below the code editor to render
them as standalone heap objects with references pointing to them, which
is what they technically are.)
Even the small gotchas that show up in multiple-choice questions
– integer division truncating, casts like (int)(q / r),
Integer.MAX_VALUE overflow wrapping around to a negative number
– become concrete when every intermediate value appears
on-screen at the step where it's computed.
For this unit (25–35% of the exam), the CED suggests having
students keep trace tables: one column per variable, one row per loop
iteration. Python Tutor works like a self-updating trace table, since
every live variable is on-screen at every step. Here is one of the
CED's standard string algorithms from topic 2.10, reversing a string
with a while loop:
At the current step, i is 2 and reversed has just grown to
"CPA". Students who mix up whether new characters get prepended or
appended can settle it by stepping one line at a time. The loop
condition, the accumulator pattern, and the final result are all
visible without any print-statement debugging.
Nested loops (topic 2.11) are where students start losing track of state in their heads. This example is the solution to a sample multiple-choice question from the CED that asks which inner loop header produces a triangle of numbers:
The print output accumulates in the gray console pane as you step, so
students see exactly when each row ends and why the inner loop bound
k < j shrinks each time around. A nice classroom exercise: paste in
one of the wrong answer choices (say, k <= j) and watch precisely
where the output diverges from the intended triangle. That's also a
gentle way into topic 2.12 on statement execution counts – the
step counter under the slider literally counts executed steps, so
comparing two loop variants becomes an observation rather than a
guess.
This unit (10–18% of the exam) is where students go from using
classes to writing them, and it maps to the Class Design
free-response question. The example below is adapted from the sample
Class Design FRQ in the CED, where students implement a
CupcakeMachine class from a specification table:
The main() method runs a shortened version of the CED's own sample
execution sequence:
c1 fills an order for 2 cupcakes at $1.75 each, then rejects an order
of 10 when only 8 remain (leaving its state unchanged), and a second
machine c2 operates with completely independent state. In the
current step (Step 13), takeOrder is mid-execution: availCupcakes
has already dropped from 10 to 8, and message was just rebuilt from
"Order cannot be filled" to the real order confirmation. Note that
the method's frame contains a this reference pointing at c1's
object. Also note that private instance variables are in plain view:
encapsulation hides fields from other classes, not from your
students, so they can finally see the object state that their accessor
and mutator methods are reading and writing.
Class (static) variables from topic 3.7 get their own display area. One of the CED's suggested activities is to give students classes that use class variables "for unique identification numbers or for counting the number of objects that have been created" and let them investigate how those variables behave. This example is exactly that investigation:
The static variable displays as RaffleTicket.totalSold in its own
area – matching the ClassName.variable notation that the CED
uses for class variables – while each ticket
object carries its own serialNum instance variable. At the current
step, the third ticket is mid-construction: totalSold has already
incremented to 3, but serialNum is still 0 until the next line runs.
Watching one shared counter feed three per-object serial numbers makes
the static-versus-instance distinction click.
Topic 3.6 (passing and returning object references) states that a
parameter is initialized with a copy of the reference, not a copy of
the object, so methods can mutate the caller's object. That's the same
arrows-into-frames story shown in the Circle example above, and my
earlier article has a dedicated example of
swapping fields between two objects passed as parameters, if you want
a ready-made demo of reference-versus-primitive parameter passing.
This is the biggest unit (30–40% of the exam and roughly a third of the school year), and two of the four free-response questions – Data Analysis with ArrayList, and 2D Array – draw directly from it.
Let's start with ArrayList. The CED motivates it with an essential
question about why an ArrayList suits your music playlist while an
array suits your class schedule, so:
The step shown is right after playlist.add(1, "Cruel Summer")
executed: the element that was at index 1 has been shifted right to
make room. Step forward to watch set replace an element without
shifting, and remove(0) shift everything left. This index arithmetic
is exactly what students must reason about on paper when exam questions
insert and remove during traversals, and here each shift is drawn at
the step where it happens. (When I wrote my earlier Java article,
ArrayList visualization was on the future-work list; it works now,
along with seven other java.util collections such as HashMap and
HashSet if your students venture beyond the AP subset.
ArrayList<Integer> works too – autoboxing from topic 4.7
happens silently, and each Integer displays as a visually distinct
boxed value so students can tell it apart from a primitive int.)
The Data Analysis with ArrayList FRQ always involves an ArrayList of
objects, so here is the CED's own sample question: averageWithinRange
must average the cost of available items whose cost falls in an
inclusive range. This is the CED's canonical solution running on the
CED's own example data:
The enhanced for loop variable it points at the current ItemInfo
object as the loop walks down the list. In the current step (Step 63),
it has reached the $40 watch and isAvailable() is about to return
false, so the watch gets skipped – step forward and watch
sum and count stay unchanged for that element. The method finally
returns 25.0, matching the CED's worked example. Students who write
their own FRQ practice solutions can paste them in and watch their
accumulator logic run item by item. (Notice that this example puts two
classes into one editor pane, with only one of them marked public.
Python Tutor doesn't support creating multiple .java files, but this
one-file pattern handles the multi-class programs that FRQs are built
around.)
Next, 2D arrays. This example searches a seating chart in row-major order, the traversal pattern from topic 4.12:
Depending on the display mode, the 2D array renders either as a
compact [row][col] grid or as separate row arrays with arrows
pointing to them. Both views teach something real: the grid matches how
exam questions draw tables, while the arrows show what Java actually
stores – a 2D array is stored as an array of arrays, as topic 4.11
of the CED puts it. On the live site, the "show array-of-arrays
as 2D array" checkbox below the editor switches between the two views.
One more detail worth pointing out to students: the element comparison
uses .equals, not == – the published scoring guidelines for
the 2D Array FRQ explicitly withhold a point for comparing strings
with ==.
Recursion (topic 4.16) is assessed only on the multiple-choice section,
and only as reading – the 2025 framework never asks students to
write recursive code. So tracing practice is exactly what students need. Here is a
sample multiple-choice question from the CED, which asks what
mystery(10, 0) prints:
The CED's suggested classroom activity for recursion is to "create a
call tree or a stack trace to show the method being called and the
values of any parameters of each call." That is literally what the
visualizer draws. At the current step (Step 8), four frames of
mystery are stacked up, each holding its own copies of j and k
– the CED's essential knowledge statement that "each recursive
call has its own set of local variables, including the parameters,"
rendered as an actual picture. Step forward to watch the frames unwind
and print 4 6 8 10.
Sorting (topic 4.15) benefits from the same treatment. This is the selection sort implementation from a sample multiple-choice question in the CED, which asks what the array contains after exactly three passes of the outer loop:
Drag the slider to Step 68 and read the answer off the screen:
{10, 20, 30, 60, 40, 50} – the first three positions are
locked in sorted order while the rest remain shuffled. Insertion sort
traces equally well, and so does merge sort: its recursive splitting
and merging fits comfortably within the visualizer's step budget for
classroom-sized arrays.
Binary search (topic 4.17) rounds out the unit:
Each recursive call narrows lo and hi, and since every frame shows
its own copies of those parameters, the "eliminate half the array each
call" behavior is visible as a stack of shrinking ranges: 0–6,
then 0–2, then found.
Finally, run-time errors. The CED's error taxonomy in topic 1.1 distinguishes syntax errors, logic errors, and run-time errors, and off-by-one errors get their own essential-knowledge bullet. Here's the classic:
The loop condition uses <= where < was intended. The program prints
5, 10, and 15 just fine, then throws an
ArrayIndexOutOfBoundsException at i == 3, and the visualizer shows
the exception at the exact step where it occurs – with i on
screen at the moment of the crash, so students can immediately see the
cause. NullPointerException and
ArithmeticException (integer division by zero) display the same way,
at the offending step rather than as a wall of terminal text.
I want to be honest about limitations so you can plan around them:
Scanner-plus-File code
won't run. (Reading keyboard input with Scanner works fine
– the visualizer prompts for each value and displays how much
of the input has been consumed at every step – but the exam's
topic 4.6 is specifically about files.) Note that the exam itself
only asks students to read file-reading code (it appears in
multiple-choice questions), and no free-response question requires
file I/O. For practice, initialize data directly in arrays,
ArrayLists, or a String that you chop up with split.var, records, or switch expressions appear on the exam
– so every language feature in the CED works fine. Python Tutor
complements your classroom IDE; it doesn't replace it.And one notable non-limitation: inheritance. The 2025 framework
removed implementing inheritance from the course, but that's a change
in the AP standards, not in the tool – the visualizer handles
inheritance, polymorphism, and super() calls well. If you still teach
those topics (say, as a post-AP unit, or if you follow an older
curriculum), my earlier article has ready-made
examples.
The CED now includes guidance on AI tools, drawing a line between uses that enhance learning (it explicitly lists "getting explanations of code behavior and execution flow" and help with debugging) and uses that undermine it (having AI write your solutions). Python Tutor sits on the useful side of that line by design: the visualization itself is not generative AI, just a faithful rendering of what the JVM actually did. There is also an optional AI tutor chat below the editor on the live site; unlike a general-purpose chatbot, it sees the student's code, the current visualization step, and any error message, so its explanations are grounded in the same diagram the student is looking at. The AI tutor is free to use, with rate limits.
The Java visualizer in Python Tutor can help your AP Computer Science A students practice the code tracing skills that the course rewards, and see the objects, references, frames, and data structures that the exam expects them to keep in their heads.
Feel free to share this direct link in relevant course materials, chat groups, mailing lists, discussion forums, social media, or anywhere else: