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

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