Skip to content

Rename leak signature to leak fingerprint - #2938

Merged
pyricau merged 1 commit into
mainfrom
make-sense-for-people-who-are
Aug 5, 2026
Merged

Rename leak signature to leak fingerprint#2938
pyricau merged 1 commit into
mainfrom
make-sense-for-people-who-are

Conversation

@pyricau

@pyricau pyricau commented Aug 5, 2026

Copy link
Copy Markdown
Member

The hash that identifies a leak was called its signature everywhere: Leak.signature and LeakTrace.signature, the Signature: line of a printed heap analysis, unreadLeakSignatures on the analysis-done event, the leak table's column, and the leak row in Shark Explorer. It's now called its leak fingerprint.

Why

Two problems with the word, both of which cost a newcomer time.

It's already taken, twice. In a Kotlin or Java codebase "signature" means a method signature, and on Android it also means the signature an APK is signed with. Both senses live in this repo — HprofRecord.methodSignatureStringId, COMPRESS_SIGNATURE in the JDWP bitmap reader, PNG_SIGNATURE, the notarization step of the release workflow, and the change log entry about a constructor's signature changing. So a reader meets three unrelated meanings of one word, and the leak one is the odd sense out.

It never said what the hash is for, which is that two leaks with the same one are caused by the same bug. "Fingerprint" says content-derived identity, matches what Sentry calls the same concept, and collides with nothing here.

The hash itself doesn't change — same input, same SHA-1 — so a leak keeps the string it already had, and a bug report or a dashboard grouped by it still lines up across the upgrade.

Naming rule

Values are leakFingerprint, prose and user-visible text say "leak fingerprint", and the function names that already say Leak take ByFingerprint. So nothing reads leak.leakFingerprint or retrieveLeakByLeakFingerprint.

Breaking changes

Was Is
LeakTrace.signature LeakTrace.leakFingerprint
Leak.signature (and both subclasses) Leak.leakFingerprint
HeapAnalysisSucceeded.unreadLeakSignatures unreadLeakFingerprints
Signature: <hash> in printed output Leak fingerprint: <hash>
"…with the same signature" "…with the same leak fingerprint"

unreadLeakFingerprints is in leakcanary-android-core's ABI, the contract AGENTS.md says to break only as a last resort — flagging it rather than assuming it's fine. The ABI diff is exactly these five accessors and nothing else.

Database

The leak.signature column becomes leak.fingerprint, mirroring how the old schema named the column after the concept and the index after both (leak_signatureleak_fingerprint). ALTER TABLE RENAME COLUMN needs SQLite 3.25, i.e. API 30, so a version 26 migration copies the table over — create, copy, drop, rename — rather than recreating the database, which would throw away the user's stored leak history.

DatabaseMigrationTest upgrades a committed v24 database and then reads it back, so it covers this. It passes on API 24 and on API 36 — either side of the SQLite version where ALTER TABLE RENAME started rewriting other tables' foreign key clauses, which is the failure mode this migration is shaped to avoid.

The standalone leakcanary-app's SQLDelight schema is renamed too. It has no migration files, which is unchanged by this.

Left alone

  • Every unrelated sense of the word: method signatures (methodSignatureStringId, FixedWindowCallback, ByteArrayTimSort), code signing (the release workflow and its doc), the JNI descriptor COMPRESS_SIGNATURE, PNG magic bytes, EqualsOnSignatureLine in the detekt config, and the // TODO Enforce package signature in LeakUiAppClient.
  • Released change log entries. Versions 2.0, 2.1 and 3.0-alpha-3 describe an API that was called signature at the time; rewriting them would make them claim otherwise. Only the ## Unreleased section is updated.

Verification

  • ./gradlew build — green, which includes checkKotlinAbi and detekt.
  • ./gradlew :leakcanary:leakcanary-android-core:connectedDebugAndroidTest — 27 tests green on API 36, and the 7 DatabaseMigrationTest tests green on API 24 as well.

🤖 Generated with Claude Code

The hash that identifies a leak was called its signature everywhere: the
`signature` property of `Leak` and `LeakTrace`, the `Signature:` line of a
printed heap analysis, the `unreadLeakSignatures` event field, the leak
table's column, and the explorer's leak row.

Two problems with the word, both of which cost a newcomer time. In a Kotlin
or Java codebase "signature" already means a method signature, and on Android
it also means the signature an APK is signed with — both of which appear in
this repo, in `HprofRecord.methodSignatureStringId`, in `COMPRESS_SIGNATURE`,
in the release workflow, and in the change log entry about a constructor. And
it never said what the hash is for, which is that two leaks with the same one
are caused by the same bug. "Fingerprint" says content-derived identity and
collides with nothing here.

The hash itself doesn't change, so a leak keeps the string it had and reports
across the upgrade still line up.

Values are `leakFingerprint`, prose is "leak fingerprint", and the function
names that already say Leak take `ByFingerprint`, so nothing reads
`leak.leakFingerprint` or `retrieveLeakByLeakFingerprint`.

The `leak.signature` column becomes `leak.fingerprint`, mirroring how the old
schema named the column after the concept and the index after both. Renaming a
column needs SQLite 3.25, i.e. API 30, so the table is copied over in a
version 26 migration rather than the database being recreated, which would
throw away the stored leak history. `DatabaseMigrationTest` upgrades a
committed v24 database, so it covers the migration; it passes on API 24 and on
API 36, either side of the SQLite version where ALTER TABLE RENAME started
rewriting other tables' foreign key clauses.

Left alone: every unrelated sense of the word, and the entries of released
change log versions, which describe an API that was called `signature` at the
time.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@pyricau
pyricau merged commit 78fe743 into main Aug 5, 2026
16 checks passed
@pyricau
pyricau deleted the make-sense-for-people-who-are branch August 5, 2026 08:09
dayanruben pushed a commit to dayanruben/leakcanary that referenced this pull request Aug 6, 2026
AGENTS.md claimed docs/api was Dokka output committed to the repo. It has
been git ignored since 5abae5d ("Prepare 2.9 release", April 2022), which
untracked every docs/api file and added the directory to .gitignore in the
same commit. Both release guides already have this right: they run
`rm -rf docs/api && ./gradlew siteDokka` before `mkdocs gh-deploy` precisely
because the directory isn't there.

That line sent me looking for a directory to regenerate after a public API
change in square#2938, which is the exact failure this file exists to prevent.

Moved out of "Things that will bite you" and onto the siteDokka command,
next to updateKotlinAbi. Nothing about a generated, ignored directory is
surprising once stated, so it isn't a bite; the useful moment for the fact
is when you've just changed the public API and are deciding what to
regenerate. Kept the half of the warning that still holds — fix the KDoc,
not the generated pages.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant