PatchHandle

class PatchHandle(val key: String, val slot: Int, val handler: Patch.CountingHandler, val unweave: Unweave, val woven: Map<Any, List<Woven>>, val seen: AtomicBoolean, val listener: Patch.WeaveListener)

One live patch: its id, what it wove, and how it has behaved since. Returned by Patches.onEnter / Patches.onExit and read back later by Patches.handle.

A live view, not a snapshot — targets fills itself in when a pending patch's class finally loads, so re-reading is the point rather than a caveat. Removal is not on it: Patches.remove is the way out, so the registry that lists a patch is also what unweaves it — and detached is what one that threw halfway leaves behind.

Constructors

Link copied to clipboard
internal constructor(key: String, slot: Int, handler: Patch.CountingHandler, unweave: Unweave, woven: Map<Any, List<Woven>>, seen: AtomicBoolean, listener: Patch.WeaveListener)

Types

Link copied to clipboard
private enum Stage : Enum<PatchHandle.Stage>

How far removal has got. DETACHED — transformer deregistered, advice still woven — is what a sweep whose retransform threw leaves behind, and what lets the next one resume instead of starting over.

Properties

Link copied to clipboard

A removal that got as far as deregistering and then threw: still listed, still woven, still firing. Nothing else here says so — fires keeps climbing and targets still names the methods — and the fix is to repeat the Patches.remove that threw.

Link copied to clipboard

Of those, how many ended in the callback throwing. A swallowed throw leaves the patched method intact and the fire counted, so a wholly broken handler reads exactly like a working one until this is read — it is what separates "never fired" from "fired and blew up every time".

Link copied to clipboard
val fires: Long

How many times the advice ran.

Link copied to clipboard
Link copied to clipboard
val id: String

What Patches.handle and Patches.remove take: the install call echoed back in the caller's own spelling, not the methods it resolved to — those are targets. Minted per install, so an id kept across a re-install reads as gone instead of naming the replacement.

Link copied to clipboard
internal val key: String

The id Patches registers this patch as, and the label its fires carry — see Patch.SEQ.

Link copied to clipboard

The last one, whole; null if the callback never threw. Its toString is the single line toString shows — the frames are here for whoever wants them.

Link copied to clipboard

Stays registered after install, so a pending patch that fails when its class arrives lands here too.

Link copied to clipboard

True while no weave has been confirmed. Usually that means the target class has not loaded — but not always, which is why toString checks before it says so. Left as the mechanical fact: making it ask would put a walk of every loaded class behind a property read.

Link copied to clipboard
private val seen: AtomicBoolean

Set the first time the target type is transformed, i.e. once the answer is actually known.

Link copied to clipboard
private val slot: Int

The bridge slot the woven advice dispatches through; key's suffix as an int, from the same mint.

Link copied to clipboard
Link copied to clipboard
internal val targetName: String

The type this patch was installed against, as Unweave.retransform batches on it.

Link copied to clipboard

The methods actually woven, each as signature @loader, or null while the target class has not been transformed yet (it isn't loaded — the patch is installed and waiting).

Link copied to clipboard
private val unweave: Unweave
Link copied to clipboard

What ByteBuddy threw while weaving, or null if the advice went in. Non-null means targets names what Patch.weave picked before the failure, not methods the advice actually reached.

Link copied to clipboard
private val woven: Map<Any, List<Woven>>

Live view, keyed by defining loader — one entry per class copy, filled in if the target class loads later and rewritten on every retransform of that copy.

Functions

Link copied to clipboard
internal fun detach()

Phase 1 of removal: deregister, leaving the advice woven. Pair with finish, one Unweave.retransform over every detached patch's class in between — that is what makes a sweep of N patches cost one retransform instead of N.

Link copied to clipboard
internal fun finish()

Phase 3: the advice is gone, so the bridge entry can go too. Unregistering any earlier would leave the still-woven advice boxing its arguments for a lookup that can never hit.

Link copied to clipboard
private fun flat(): List<Woven>

Every copy's entry in one list, sorted: the map orders by nothing a caller should see.

Link copied to clipboard
open override fun toString(): String
Link copied to clipboard
internal fun wovenParams(): List<List<String>>?

targets in the form a signature filter takes, null under the same "not known yet" condition.