diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ReflectiveAccess.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ReflectiveAccess.kt index d07549d6557..a37f5090130 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ReflectiveAccess.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ReflectiveAccess.kt @@ -74,7 +74,7 @@ internal class ReflectiveAccessLowering( // Wrapper for the logic from SyntheticAccessorLowering private fun IrSymbol.isAccessible(withSuper: Boolean = false): Boolean { - return isAccessible(context, currentScope, inlineScopeResolver, withSuper, null) + return isAccessible(context, currentScope, inlineScopeResolver, withSuper, null, fromOtherClassLoader = true) } // Fragments are transformed in a post-order traversal: children first, diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt index 2e362efd33e..3c29697b24e 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt @@ -55,6 +55,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : FileL currentScope: ScopeWithIr?, inlineScopeResolver: IrInlineScopeResolver, withSuper: Boolean, thisObjReference: IrClassSymbol?, + fromOtherClassLoader: Boolean = false ): Boolean { /// We assume that IR code that reaches us has been checked for correctness at the frontend. /// This function needs to single out those cases where Java accessibility rules differ from Kotlin's. @@ -92,8 +93,9 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : FileL return when { jvmVisibility == 0 /* package only */ -> samePackage jvmVisibility == Opcodes.ACC_PRIVATE -> ownerClass == scopeClassOrPackage - // JVM `protected`, unlike Kotlin `protected`, permits accesses from the same package. - !withSuper && samePackage -> true + // JVM `protected`, unlike Kotlin `protected`, permits accesses from the same package, + // provided the call is not across class loader boundaries. + !withSuper && samePackage && !fromOtherClassLoader -> true // Super calls and cross-package protected accesses are both only possible from a subclass of the declaration // owner. Also, the target of a non-static call must be assignable to the current class. This is a verification // constraint: https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.10.1.8