Skip to content

Migration and troubleshooting

Jordan Samhi edited this page Oct 25, 2026 · 4 revisions

Migration and troubleshooting

Moving from 1.1.8 to 2.0.0

This guide covers 2.0.0. Until publication completes, build and install the checkout locally with JDK 17 or later before changing a consumer's dependency; see Getting started. Soot is pinned to 4.7.1 and FlowDroid to 2.15.1; Java 8 and Java 11 integrations must upgrade their runtime and build JDK.

Older workflow Current approach
Manually initialize FlowdroidUtils and manage global Soot state Use AndroidAnalysis with try-with-resources; low-level helpers remain available
Reset metric/source-sink singletons between APKs Use session-owned metrics and immutable SourceSinkConfiguration
Parse strings returned by runTaintAnalysis() Use TaintAnalysisResult with explicit status, endpoints, paths, and diagnostics
Repeatedly scan a live call graph Capture CallGraphSnapshot and query its indexes
Reimplement graph traversal and parse saved graph text Use reachability/shortest-path queries and versioned GraphJson import/export
Build a full graph just to inspect method bodies Opt into InitializationMode.CLASSES_ONLY; graphs are prepared when requested
Initialize Soot to extract manifest attributes Use ApkInfo.read(apk), which does not require an SDK or Soot session
Subclass AndroidAppInspector for every inspection Register only needed Inspection callbacks
Register Logger.v() transformations in Soot packs Construct a context-bound Logger and pass an explicit pipeline to analysis.apply(...)
Let CLI parsing terminate the process Inspect ParseResult, print help, and choose an exit code in your executable
Expect TimeOut(int) to exit the JVM Observe its cancellation token or supply a callback; prefer Deadline and CancellationSource
Rely on bundled console/log4j setup Select and configure an SLF4J provider in the calling application

Legacy singleton accessors remain for compatibility where an instance API replaces them, but are deprecated. AndroidAppInspector callbacks now default to no-ops; its run() remains available and runIn(context) accepts a caller-owned context. The old wiki's Instrumenter examples referred to an unavailable class: use instrumentation.Logger.

SourcesSinksManager starts with bundled definitions and adds loaded files. SourceSinkConfiguration.fromFile(path) uses only definitions from that file; builder().include(...) combines configurations explicitly. A new managed session starts with an empty configuration.

Common errors

Symptom What to check
Cannot resolve androspecter:2.0.0 Until publication completes, run mvn clean install in the library checkout using the same local Maven repository as the consumer
AndroidAnalysis or another new class is missing Inspect the resolved dependency version; the historical 1.1.8 release does not contain the 2.0.0 session APIs
Unsupported class-file version Check both java -version and mvn -version; use Java 17 or later
no main manifest attribute Run the standalone cli/target/androspecter-cli.jar; the library and examples' thin JARs use library/classpath workflows. See Command-line tool
SLF4J reports no provider, or expected logs are absent Add one compatible SLF4J 2.x provider to the application; the library supplies the facade only
Missing Android classes/platform errors Pass the SDK platforms directory and ensure it contains platform JARs
Another AndroidAnalysis is open Close the owning session before opening the next; use separate JVMs for parallel work
Context is closed, belongs to another thread, or Soot was reset Keep live calls on the creating thread and avoid external G.reset() during the session
Empty taint findings Check status and diagnostics first, then definitions, exact Jimple signatures, entry points, and backend warnings
Deadline expires but processing continues Cancellation is cooperative; keep the session until the running operation returns
Graph has fewer nodes than declared methods Snapshots captured from Soot include methods incident to edges; imported or explicitly built snapshots can also retain isolated nodes
Imported graph JSON is rejected Check the schema version and required node/edge fields; use GraphJson, not reflection-based serialization of the snapshot
A manifest attribute is null It may be absent or resource-backed; inspect raw typed attributes and do not infer defaults from null
Release deployment still targets OSSRH Use the release profile with Central Portal credentials; see the repository release guide
No instrumented APK appears The instance instrumentation API changes the in-memory model; exporting and signing are separate steps

Calling analysis.context().close() invalidates that borrowed view but does not release managed-session ownership. Always close AndroidAnalysis itself.

Interpret results carefully

SUCCESS means the backend completed according to its reported state. It does not prove soundness or absence of vulnerabilities. Parser, typing, and resource warnings may be logged separately from structured result diagnostics. Findings from incomplete runs can still be inspected, but an empty incomplete result must not be treated as a completed negative analysis.

Graph snapshots allocate strings and indexes in addition to the live Soot model. Retain only the snapshots needed by your application, and size the JVM heap for your APK and analysis scope. A snapshot remains valid after close; borrowed Soot objects do not.

FlowDroid phase timeouts are rounded up to whole seconds; zero disables a limit. A callback timeout can produce a partial graph. AndroidAppsProcessor uses minutes, while legacy TimeOut uses seconds.

Validation evidence

Development validation on 2026-10-23 with Java 17 included 206 passing library tests, including two SDK-enabled tests using the reproducible APK fixture; strict public Javadoc checks; and execution of all eight runnable examples. The fixture produced one source-to-sink finding with a reconstructed path. Class-only loading preserved body edits during graph construction, and repeated taint analysis and graph rebuilding preserved valid local-variable declarations. An internal compatibility adapter handles FlowDroid 2.15.1's local-restoration issue; graph-only backend exceptions now propagate instead of being silently accepted.

Graph JSON export/import and offline queries ran after session close; Graphviz rendered the exported DOT. Instrumentation changed the fixture graph from 33 to 55 edges, with 22 added edge occurrences and an unchanged original snapshot. The metadata and class-only examples also ran on Word Snake, with the latter selecting 23 methods and 131 invocation sites before Android model generation.

The standalone CLI passed 18 tests, including two SDK-enabled tests, and strict public Javadoc checks. The packaged executable ran all five commands, including real APK taint analysis, cancellation, and offline JSON/DOT/HTML export. Graphviz rendered its DOT output. Browser checks exercised HTML method search, caller/callee filtering, call-site details, zoom, and pan; a separate viewer test covered a graph with 30001 methods. The Word Snake package-filtered report retained 12 methods and 3 edges from a full graph with 22214 methods and 925269 edges. Those filtered counts exclude calls with an endpoint outside the selected package.

The Central publishing profile generated a local non-snapshot bundle with source and Javadoc JARs and verified checksums using upload suppression. This was an unsigned local dry run: credentials, signing, and Central's server-side acceptance were not tested, and no Maven artifact was published. See the repository release guide.

Earlier full-graph validation of Word Snake (justinasmegames.wordsnake) retained 6215 loaded application classes, 30 methods and 437 Jimple statements in its manifest package, and 925269 call-graph edges. Two upstream Failed Typing diagnostics and unsupported FLAG_WEAK resource warnings remained. Completion was not evidence that these warnings were harmless or that the graph was complete.

Clone this wiki locally