You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
jadx already has everything needed to produce a program-wide call graph, but it
is only reachable as a GUI dialog. Please expose a headless, whole-program
call-graph builder in jadx-core (jadx.api) plus an export option
(DOT / JSON) usable from the API and the CLI without opening the GUI.
What already exists (and why it's not enough)
Edge primitives — already public on master, exactly right:
GUI-only (Swing dialog, GraphViz render) no programmatic entry point
and no data export.
CLI --cfg / --raw-cfg save a per-method control-flow graph to DOT a different thing entirely (intra-method, not the call graph).
So today, anyone building static-analysis tooling on jadx (reachability,
taint/call-graph analysis, security scanners) has to re-walk classes and
methods and re-assemble the graph from the primitives by hand, plus re-derive
everything getUsed() does not include (reflection Class.forName, X.class constant refs, intent-action dispatch, etc.).
Proposed API
A small builder in jadx.api that materializes the program-wide graph from the
existing primitives:
Internally this is the same getUsed()/getUnresolvedUsed()/getUseIn() walk the
GUI already does just hoisted into core, run over getClasses() with no depth
cap, and given an export writer. (getUsed() requires JadxArgs.setUsageInfoCache(new InMemoryUsageInfoCache()), which the builder can
set/validate itself.)
Proposed CLI
jadx --call-graph dot -d out app.apk # write out/callgraph.dot
jadx --call-graph json -d out app.apk # write out/callgraph.json
enables headless / CI / batch analysis (no Swing, no GraphViz needed for JSON),
a single canonical implementation instead of every downstream tool
re-deriving the graph slightly differently,
the GUI graph dialog could then be a thin consumer of the same core builder.
Nice-to-haves (optional, can be follow-ups)
include the edges getUsed() currently omits, or flag them as a separate edge
kind: reflection (Class.forName, X.class), intent-action dispatch.
(Related: the throws / constant-value usage gap see companion request.)
per-edge call-site metadata (arg constants), so consumers don't re-walk
instructions to recover literal arguments.
Happy to help with a PR the hard part (edge computation) already exists; this
is mostly hoisting + an export writer.
Environment
jadx-core master 9d4babc (also on nightly r2658.c3f7027)
Summary
jadx already has everything needed to produce a program-wide call graph, but it
is only reachable as a GUI dialog. Please expose a headless, whole-program
call-graph builder in
jadx-core(jadx.api) plus an export option(DOT / JSON) usable from the API and the CLI without opening the GUI.
What already exists (and why it's not enough)
Edge primitives — already public on master, exactly right:
JavaMethod.getUsed()resolved calleesJavaMethod.getUnresolvedUsed()unresolved (framework/lib) calleesJavaMethod.getUseIn()callersOverrideMethodVisitor, names post-rename.These are per-method only assembling the whole graph is left entirely to
the consumer.
GUI graph views (PR feat: Graph views, code pane sync, and more #2784, merged) not reusable headless:
jadx-gui/.../graphs/CallGraphDialog.javabuilds a graph, but it isJavaMethod(not the whole program),callerDepthLimit/calleeDepthLimit),and no data export.
CLI
--cfg/--raw-cfgsave a per-method control-flow graph to DOT a different thing entirely (intra-method, not the call graph).So today, anyone building static-analysis tooling on jadx (reachability,
taint/call-graph analysis, security scanners) has to re-walk classes and
methods and re-assemble the graph from the primitives by hand, plus re-derive
everything
getUsed()does not include (reflectionClass.forName,X.classconstant refs, intent-action dispatch, etc.).Proposed API
A small builder in
jadx.apithat materializes the program-wide graph from theexisting primitives:
Internally this is the same
getUsed()/getUnresolvedUsed()/getUseIn()walk theGUI already does just hoisted into core, run over
getClasses()with no depthcap, and given an export writer. (
getUsed()requiresJadxArgs.setUsageInfoCache(new InMemoryUsageInfoCache()), which the builder canset/validate itself.)
Proposed CLI
JSON form (stable, tool-friendly) — e.g.:
{ "nodes": [{"id": 0, "method": "com.example.A.foo()V"}], "edges": [{"from": 0, "to": 1, "resolved": true}] }Why core, not GUI
re-deriving the graph slightly differently,
Nice-to-haves (optional, can be follow-ups)
getUsed()currently omits, or flag them as a separate edgekind: reflection (
Class.forName,X.class), intent-action dispatch.(Related: the
throws/ constant-value usage gap see companion request.)instructions to recover literal arguments.
Happy to help with a PR the hard part (edge computation) already exists; this
is mostly hoisting + an export writer.
Environment
9d4babc(also on nightlyr2658.c3f7027)JadxDecompiler(library use), headless analysis pipeline