Skip to content

Instantly share code, notes, and snippets.

@izantech
Created November 21, 2025 17:01
Show Gist options
  • Select an option

  • Save izantech/f383836effd9f2c0a0567c615f489a73 to your computer and use it in GitHub Desktop.

Select an option

Save izantech/f383836effd9f2c0a0567c615f489a73 to your computer and use it in GitHub Desktop.
IllegalAccessError sample
Exception in thread "main" java.lang.IllegalAccessError: class dagger.app.izantech.di.sharding.di.ApplicationComponent$Impl$Shard tried to access private field dagger.app.izantech.di.sharding.di.ApplicationComponent$Impl.authenticationApiServiceImplProvider (dagger.app.izantech.di.sharding.di.ApplicationComponent$Impl$Shard and dagger.app.izantech.di.sharding.di.ApplicationComponent$Impl are in unnamed module of loader 'app')
at dagger.app.izantech.di.sharding.di.ApplicationComponent$Impl$Shard.<init>(ApplicationComponent.kt)
at dagger.app.izantech.di.sharding.di.ApplicationComponent$Impl.<init>(ApplicationComponent.kt:13)
at dagger.app.izantech.di.sharding.di.ApplicationComponent$Impl.<init>(ApplicationComponent.kt)
at dagger.app.izantech.di.sharding.di.ApplicationComponent$Factory$Impl.create(ApplicationComponent.kt:79)
at app.izantech.di.sharding.MainKt.main(Main.kt:33)
@Deprecated(message = "This synthesized declaration should not be used directly", level = DeprecationLevel.HIDDEN)
@MetroImplMarker
class Impl : ApplicationComponent {
private constructor(@BindsInstance logger: AppLogger, @BindsInstance connectivityMonitor: ConnectivityMonitor, @BindsInstance preferences: AppPreferences, @BindsInstance cacheManager: CacheManager, @BindsInstance dispatchers: CoroutineDispatchers) /* primary */ {
super/*Any*/()
/* <init>() */
<this>.Shard()
<this>.Shard2()
<this>.Shard3()
<this>.Shard4()
<this>.Shard5()
<this>.Shard6()
<this>.Shard7()
<this>.Shard8()
}
override fun inject(target: TestMemberInjection) {
Companion.injectLogger(instance = target, logger = <this>.#loggerInstanceProvider.invoke())
Companion.injectIotApiService(instance = target, iotApiService = <this>.#iotApiServiceImplProvider.invoke())
}
// ... some graph extensions
private val loggerInstanceProvider: Provider<AppLogger>
field = Companion.invoke<AppLogger>(value = logger)
private val connectivityMonitorInstanceProvider: Provider<ConnectivityMonitor>
field = Companion.invoke<ConnectivityMonitor>(value = connectivityMonitor)
private val thisGraphInstance: ApplicationComponent
field = <this>
private val applicationComponentProvider: Provider<ApplicationComponent>
field = Companion.invoke<ApplicationComponent>(value = <this>.#thisGraphInstance)
private val authenticationApiServiceImplProvider: Provider<AuthenticationApiServiceImpl>
private val authorizationApiServiceImplProvider: Provider<AuthorizationApiServiceImpl>
private val billingApiServiceImplProvider: Provider<BillingApiServiceImpl>
private val catalogApiServiceImplProvider: Provider<CatalogApiServiceImpl>
// ... some more properties
inner class Shard {
constructor() /* primary */ {
super/*Any*/()
/* <init>() */
<this>.#authenticationApiServiceImplProvider = Companion.provider<Provider<AuthenticationApiServiceImpl>, AuthenticationApiServiceImpl>(delegate = Companion.create(logger = <this>.#loggerInstanceProvider, connectivityMonitor = <this>.#connectivityMonitorInstanceProvider))
<this>.#authorizationApiServiceImplProvider = Companion.provider<Provider<AuthorizationApiServiceImpl>, AuthorizationApiServiceImpl>(delegate = Companion.create(logger = <this>.#loggerInstanceProvider, connectivityMonitor = <this>.#connectivityMonitorInstanceProvider))
}
}
inner class Shard2 {
constructor() /* primary */ {
super/*Any*/()
/* <init>() */
<this>.#billingApiServiceImplProvider = Companion.provider<Provider<BillingApiServiceImpl>, BillingApiServiceImpl>(delegate = Companion.create(logger = <this>.#loggerInstanceProvider, connectivityMonitor = <this>.#connectivityMonitorInstanceProvider))
<this>.#catalogApiServiceImplProvider = Companion.provider<Provider<CatalogApiServiceImpl>, CatalogApiServiceImpl>(delegate = Companion.create(logger = <this>.#loggerInstanceProvider, connectivityMonitor = <this>.#connectivityMonitorInstanceProvider))
}
}
// ... some more shards
}
// Copyright (C) 2025 Zac Sweers
// SPDX-License-Identifier: Apache-2.0
package dev.zacsweers.metro.compiler.ir.graph
import dev.zacsweers.metro.compiler.NameAllocator
import dev.zacsweers.metro.compiler.Origins
import dev.zacsweers.metro.compiler.asName
import dev.zacsweers.metro.compiler.ir.IrMetroContext
import dev.zacsweers.metro.compiler.ir.generateDefaultConstructorBody
import dev.zacsweers.metro.compiler.ir.setDispatchReceiver
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
import org.jetbrains.kotlin.ir.builders.irCallConstructor
import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.addChild
import org.jetbrains.kotlin.ir.util.copyTo
import org.jetbrains.kotlin.ir.util.createThisReceiverParameter
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.name.SpecialNames
context(context: IrMetroContext)
internal fun generateShards(
graphClass: IrClass,
statements: List<InitStatement>,
nameAllocator: NameAllocator,
keysPerShard: Int,
): List<InitStatement> {
return statements.chunked(keysPerShard).map { shard ->
val shardName = nameAllocator.newName("Shard")
val shardClass = context.irFactory.buildClass {
name = shardName.asName()
origin = Origins.GraphShardClassDeclaration
kind = ClassKind.CLASS
isInner = true
}
graphClass.addChild(shardClass)
val graphThis = graphClass.thisReceiver!!
// Set thisReceiver for the inner class
shardClass.createThisReceiverParameter()
// Add constructor with outer class dispatch receiver
val shardConstructor = context.irFactory.buildConstructor {
isPrimary = true
returnType = shardClass.symbol.typeWith(emptyList())
name = SpecialNames.INIT
}.apply {
parent = shardClass
// Inner class constructor needs the outer class instance as dispatch receiver
setDispatchReceiver(graphClass.thisReceiver!!.copyTo(this, type = graphClass.defaultType))
body = generateDefaultConstructorBody {
for (statement in shard) {
+statement(this, graphThis)
}
}
}
shardClass.addChild(shardConstructor)
val initCall: InitStatement = {
irCallConstructor(shardConstructor.symbol, emptyList()).apply {
arguments[0] = irGet(graphThis)
}
}
initCall
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment