Skip to main content

JVM Instrumentation

Kanvas attaches a Java instrumentation agent at application startup and transforms specific Skiko/Skia classes as they are loaded.

The entry point is KanvasAgent.java.

Why instrument the existing renderer?​

The design goal is to keep the target application structurally normal:

existing Compose application
│
▼
existing Skiko host/window
│
▼
Kanvas observes + intercepts final rendering work

Replacing the application's entire windowing stack would make integration substantially more invasive and would force Kanvas to recreate behavior that Compose Desktop and Skiko already own.

Instrumentation instead lets Kanvas attach at known renderer boundaries.

The agent is intentionally narrow

The agent does not transform every application class. It registers transformers for specific Skiko/Skia rendering classes and related objects such as paragraphs, shaders, image filters, mask filters, color filters, and path effects.

What the agent records​

The audit layer tracks:

  • whether Compose scene classes loaded
  • whether default Skia/Skiko renderer classes loaded
  • which runtime JARs those classes came from
  • whether frame-boundary transforms were installed
  • whether takeover was armed
  • whether strict renderer ownership failed

This is why renderer debugging starts with the audit log instead of only looking at pixels.

Strict mode​

strictRenderer is a verification tool, not a performance mode.

When strict mode is active and Kanvas is not performing takeover, loading the default renderer path is treated as an ownership failure.

That behavior is deliberate: strict mode exists to expose "the app rendered, but not through the renderer we thought it used."

Strict mode can stop the JVM

Renderer-ownership failures are intentionally hard failures in strict verification mode. Do not enable strict mode in a production configuration unless that behavior is explicitly desired.

Source: KanvasAgent.java