From 683489687e7c330bc251dd60f2028e6ac41ce295 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 8 Apr 2020 20:20:50 +0200 Subject: [PATCH] Fix NPE in KCallable.isAccessible for interfaces loaded by boot class loader Class.getClassLoader returns null for classes loaded by the system class loader (the one used to start the application). In this case we need to use ClassLoader.getSystemClassLoader. We already have an extension `safeClassLoader` specifically for this purpose in reflection.jvm, but forgot to use it in d59f2bcc80. #KT-37707 Fixed --- .../ir/FirBlackBoxCodegenTestGenerated.java | 5 +++++ .../functions/isAccessibleOnAllMembers.kt | 20 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 +++++ .../LightAnalysisModeTestGenerated.java | 5 +++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 +++++ .../jvm/internal/KDeclarationContainerImpl.kt | 2 +- 6 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/codegen/box/reflection/functions/isAccessibleOnAllMembers.kt diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 7e856cdc064..8a582dd9314 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -23938,6 +23938,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/reflection/functions/instanceOfFunction.kt"); } + @TestMetadata("isAccessibleOnAllMembers.kt") + public void testIsAccessibleOnAllMembers() throws Exception { + runTest("compiler/testData/codegen/box/reflection/functions/isAccessibleOnAllMembers.kt"); + } + @TestMetadata("javaClassGetFunctions.kt") public void testJavaClassGetFunctions() throws Exception { runTest("compiler/testData/codegen/box/reflection/functions/javaClassGetFunctions.kt"); diff --git a/compiler/testData/codegen/box/reflection/functions/isAccessibleOnAllMembers.kt b/compiler/testData/codegen/box/reflection/functions/isAccessibleOnAllMembers.kt new file mode 100644 index 00000000000..dfed40d9324 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/functions/isAccessibleOnAllMembers.kt @@ -0,0 +1,20 @@ +// TARGET_BACKEND: JVM +// IGNORE_BACKEND_FIR: JVM_IR +// WITH_REFLECT + +import kotlin.reflect.jvm.isAccessible + +fun box(): String { + val members = Observer::class.members + for (member in members) { + member.isAccessible = true + } + return members.single { it.name == "result" }.call(Observer()) as String +} + +class Observer : AutoCloseable { + override fun close() { + } + + private fun result() = "OK" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index e6cc56f08a7..6dcae302a26 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -25524,6 +25524,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/reflection/functions/instanceOfFunction.kt"); } + @TestMetadata("isAccessibleOnAllMembers.kt") + public void testIsAccessibleOnAllMembers() throws Exception { + runTest("compiler/testData/codegen/box/reflection/functions/isAccessibleOnAllMembers.kt"); + } + @TestMetadata("javaClassGetFunctions.kt") public void testJavaClassGetFunctions() throws Exception { runTest("compiler/testData/codegen/box/reflection/functions/javaClassGetFunctions.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 962e96c5339..27b7dc28ddd 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -24341,6 +24341,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/reflection/functions/instanceOfFunction.kt"); } + @TestMetadata("isAccessibleOnAllMembers.kt") + public void testIsAccessibleOnAllMembers() throws Exception { + runTest("compiler/testData/codegen/box/reflection/functions/isAccessibleOnAllMembers.kt"); + } + @TestMetadata("javaClassGetFunctions.kt") public void testJavaClassGetFunctions() throws Exception { runTest("compiler/testData/codegen/box/reflection/functions/javaClassGetFunctions.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index e259032337c..ede7f6ec53a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -23938,6 +23938,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/reflection/functions/instanceOfFunction.kt"); } + @TestMetadata("isAccessibleOnAllMembers.kt") + public void testIsAccessibleOnAllMembers() throws Exception { + runTest("compiler/testData/codegen/box/reflection/functions/isAccessibleOnAllMembers.kt"); + } + @TestMetadata("javaClassGetFunctions.kt") public void testJavaClassGetFunctions() throws Exception { runTest("compiler/testData/codegen/box/reflection/functions/javaClassGetFunctions.kt"); diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KDeclarationContainerImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KDeclarationContainerImpl.kt index 95efb814b59..a6a8de7b4f8 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KDeclarationContainerImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KDeclarationContainerImpl.kt @@ -184,7 +184,7 @@ internal abstract class KDeclarationContainerImpl : ClassBasedDeclarationContain // Static "$default" methods should be looked up in each DefaultImpls class, see KT-33430 if (isStaticDefault) { - val defaultImpls = superInterface.classLoader.tryLoadClass(superInterface.name + JvmAbi.DEFAULT_IMPLS_SUFFIX) + val defaultImpls = superInterface.safeClassLoader.tryLoadClass(superInterface.name + JvmAbi.DEFAULT_IMPLS_SUFFIX) if (defaultImpls != null) { parameterTypes[0] = superInterface defaultImpls.tryGetMethod(name, parameterTypes, returnType)?.let { return it }