From 559da842c08b1b7b853bba5b4a3f434fcd50565a Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 13 Feb 2017 11:57:40 +0300 Subject: [PATCH] Clear reflection caches in black box codegen tests To prevent tests from altering outcomes of the subsequent tests. Also expose the clearCaches method (in the internal class ReflectionFactoryImpl) so that it can be used in other places in similar circumstances --- .../codegen/AbstractBlackBoxCodegenTest.java | 18 ++++++++++++++++++ .../jvm/internal/ReflectionFactoryImpl.java | 7 +++++++ .../kotlin/reflect/jvm/internal/kClassCache.kt | 4 ++++ .../jvm/internal/moduleByClassLoader.kt | 6 +++++- 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/compiler/tests-common/org/jetbrains/kotlin/codegen/AbstractBlackBoxCodegenTest.java b/compiler/tests-common/org/jetbrains/kotlin/codegen/AbstractBlackBoxCodegenTest.java index 13dfb4b17a2..87e3d9bc789 100644 --- a/compiler/tests-common/org/jetbrains/kotlin/codegen/AbstractBlackBoxCodegenTest.java +++ b/compiler/tests-common/org/jetbrains/kotlin/codegen/AbstractBlackBoxCodegenTest.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil; +import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.psi.KtDeclaration; import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.psi.KtNamedFunction; @@ -159,6 +160,23 @@ public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase { System.out.println(generateToText()); throw ExceptionUtilsKt.rethrow(e); } + finally { + clearReflectionCache(generatedClassLoader); + } + } + } + + private static void clearReflectionCache(@NotNull ClassLoader classLoader) { + try { + Class klass = classLoader.loadClass(JvmAbi.REFLECTION_FACTORY_IMPL.asSingleFqName().asString()); + Method method = klass.getDeclaredMethod("clearCaches"); + method.invoke(null); + } + catch (ClassNotFoundException e) { + // This is OK for a test without kotlin-reflect in the dependencies + } + catch (Exception e) { + throw ExceptionUtilsKt.rethrow(e); } } diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java index 5e6133e8961..5da0e5fc514 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java @@ -105,4 +105,11 @@ public class ReflectionFactoryImpl extends ReflectionFactory { KDeclarationContainer owner = reference.getOwner(); return owner instanceof KDeclarationContainerImpl ? ((KDeclarationContainerImpl) owner) : EmptyContainerForLocal.INSTANCE; } + + // Misc + + public static void clearCaches() { + KClassCacheKt.clearKClassCache(); + ModuleByClassLoaderKt.clearModuleByClassLoaderCache(); + } } diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/kClassCache.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/kClassCache.kt index 93422cc0f0c..1cf079ad016 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/kClassCache.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/kClassCache.kt @@ -64,3 +64,7 @@ internal fun getOrCreateKotlinClass(jClass: Class): KClassImpl { K_CLASS_CACHE = K_CLASS_CACHE.plus(name, WeakReference(newKClass)) return newKClass } + +internal fun clearKClassCache() { + K_CLASS_CACHE = HashPMap.empty() +} diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/moduleByClassLoader.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/moduleByClassLoader.kt index 7ae12643d26..2e7a25db119 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/moduleByClassLoader.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/moduleByClassLoader.kt @@ -41,7 +41,7 @@ private class WeakClassLoaderBox(classLoader: ClassLoader) { identityHashCode override fun toString() = - ref.get()?.let { it.toString() } ?: "" + ref.get()?.toString() ?: "" } internal fun Class<*>.getOrCreateModule(): RuntimeModuleData { @@ -70,3 +70,7 @@ internal fun Class<*>.getOrCreateModule(): RuntimeModuleData { key.temporaryStrongRef = null } } + +internal fun clearModuleByClassLoaderCache() { + moduleByClassLoader.clear() +}