Skip to content

Reduce reflection cost on the SDK init path #5640

Description

@runningcode

Analysis of the customer-provided Perfetto trace (sentryinvest) showed reflective class-availability probing is a meaningful part of SentryAndroid.init main-thread cost: io.sentry.util.LoadClass.isClassAvailable/loadClassClass.forName ran ~22-24 times during init, and the calls triggered unrelated static initializers (e.g. androidx.compose.ui.node.Owner.<clinit>, FragmentLifecycleIntegration.<clinit>) plus ClassNotFoundException for absent integrations.

This is delivered as a stacked PR (collection #5634), squash-merged into main once the three stack PRs below merge.

Changes

[1] Probe without initializing — #5635
LoadClass.loadClass used Class.forName(name) (initializes the class). Switched to Class.forName(name, false, classLoader) so a mere availability probe no longer runs the class's static initializer; it initializes lazily on first real use.

[2] Cache lookups + collapse double-probes — #5636
Class presence is fixed for the process lifetime, so LoadClass now caches results (including "not available"). Also collapsed the isClassAvailable-then-loadClass double Class.forName in SpanFactoryFactory and ScopesStorageFactory into a single loadClass call.

[3] Gate Compose probes — #5637
The Compose gesture / view-hierarchy class probes ran during init unconditionally. Gated the gesture locators behind enableUserInteractionBreadcrumbs || enableUserInteractionTracing and the Compose view-hierarchy exporter behind attachViewHierarchy, so the Compose probes only run when a feature that consumes them is enabled.

Pixel 3 benchmarks (Android 12, ART method trace → Perfetto trace_processor)

  • [1] Probing a class with a static initializer: <clinit> invocations 1 → 0.
  • [2] Repeat probe of an absent class (untraced): 25,872 ns → 137 ns per probe (~188×).
  • [3] Features off: Compose class probes 3 → 0, ClassNotFoundException constructions 9 → 0.

Follow-up (not in this issue)

Build-time elimination of isClassAvailable via the Sentry Android Gradle Plugin (generated availability constants), which would remove the remaining integration probes entirely.

Metadata

Metadata

Assignees

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions