mhalbritter / kotlin-graalvm-reflection

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Reflection in Kotlin in native-image

The class Foo is defined as follows:

class Foo {
    fun a_method1(): A? {
        return null
    }

    fun b_method2(): B? {
        return null
    }
}

interface A

interface B

Reflection metadata for method is missing

val javaMethod = Foo::a_method1.javaMethod

will fail with

Exception in thread "main" kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Could not compute caller for function: public final fun a_method1(): test.A? defined in test.Foo[DeserializedSimpleFunctionDescriptor@1da402a9] (member = null)
        at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:88)
        at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:61)
        at kotlin.reflect.jvm.internal.ReflectProperties$LazyVal.invoke(ReflectProperties.java:63)
        at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
        at kotlin.reflect.jvm.internal.KFunctionImpl.getCaller(KFunctionImpl.kt:61)
        at kotlin.reflect.jvm.ReflectJvmMapping.getJavaMethod(ReflectJvmMapping.kt:63)
        at test.MainKt.main(Main.kt:10)
        at test.MainKt.main(Main.kt)

if reflection metadata for Foo.a_method1 is missing.

Reflection metadata for some methods in the class are missing

val javaMethod = Foo::a_method1.javaMethod
ResolvableType.forMethodReturnType(javaMethod)

will work if there is reflection metadata for Foo.a_method1 but not for Foo.b_method2.

val javaMethod = Foo::b_method2.javaMethod
ResolvableType.forMethodReturnType(javaMethod)

will not work if there is reflection metadata for Foo.b_method2 but not for Foo.a_method1.

The reason is that Kotlin iterates over the methods until it finds the matching one. This code is in kotlin.reflect.jvm.ReflectJvmMapping.getKotlinFunction(ReflectJvmMapping.kt:136). a_method1 will be iterated first (I assume because of alphabetical sorting), it then tries to inspect it (no idea why, we didn't ask for it) and then it will fail with:

Exception in thread "main" java.lang.ClassNotFoundException: test.A
        at java.base@17.0.5/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:52)
        at java.base@17.0.5/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
        at java.base@17.0.5/java.lang.ClassLoader.loadClass(ClassLoader.java:132)
        at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.parseType(KDeclarationContainerImpl.kt:273)
        at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.loadReturnType(KDeclarationContainerImpl.kt:288)
        at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.findMethodBySignature(KDeclarationContainerImpl.kt:198)
        at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:68)
        at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:61)
        at kotlin.reflect.jvm.internal.ReflectProperties$LazyVal.invoke(ReflectProperties.java:63)
        at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
        at kotlin.reflect.jvm.internal.KFunctionImpl.getCaller(KFunctionImpl.kt:61)
        at kotlin.reflect.jvm.ReflectJvmMapping.getJavaMethod(ReflectJvmMapping.kt:63)
        at kotlin.reflect.jvm.ReflectJvmMapping.getKotlinFunction(ReflectJvmMapping.kt:136)
        at org.springframework.core.MethodParameter$KotlinDelegate.getGenericReturnType(MethodParameter.java:914)
        at org.springframework.core.MethodParameter.getGenericParameterType(MethodParameter.java:510)
        at org.springframework.core.SerializableTypeWrapper$MethodParameterTypeProvider.getType(SerializableTypeWrapper.java:291)
        at org.springframework.core.SerializableTypeWrapper.forTypeProvider(SerializableTypeWrapper.java:107)
        at org.springframework.core.ResolvableType.forType(ResolvableType.java:1413)
        at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1334)
        at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1316)
        at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1283)
        at org.springframework.core.ResolvableType.forMethodReturnType(ResolvableType.java:1228)
        at test.MainKt.main(Main.kt:12)
        at test.MainKt.main(Main.kt)

test.A is the return type of a_method1 which is not in the native image.

If metadata is added for test.A, it fails with a different exception:

Exception in thread "main" kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Could not compute caller for function: public final fun a_method1(): test.A? defined in test.Foo[DeserializedSimpleFunctionDescriptor@33119311] (member = null)
        at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:88)
        at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:61)
        at kotlin.reflect.jvm.internal.ReflectProperties$LazyVal.invoke(ReflectProperties.java:63)
        at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
        at kotlin.reflect.jvm.internal.KFunctionImpl.getCaller(KFunctionImpl.kt:61)
        at kotlin.reflect.jvm.ReflectJvmMapping.getJavaMethod(ReflectJvmMapping.kt:63)
        at kotlin.reflect.jvm.ReflectJvmMapping.getKotlinFunction(ReflectJvmMapping.kt:136)
        at org.springframework.core.MethodParameter$KotlinDelegate.getGenericReturnType(MethodParameter.java:914)
        at org.springframework.core.MethodParameter.getGenericParameterType(MethodParameter.java:510)
        at org.springframework.core.SerializableTypeWrapper$MethodParameterTypeProvider.getType(SerializableTypeWrapper.java:291)
        at org.springframework.core.SerializableTypeWrapper.forTypeProvider(SerializableTypeWrapper.java:107)
        at org.springframework.core.ResolvableType.forType(ResolvableType.java:1413)
        at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1334)
        at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1316)
        at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1283)
        at org.springframework.core.ResolvableType.forMethodReturnType(ResolvableType.java:1228)
        at test.MainKt.main(Main.kt:12)
        at test.MainKt.main(Main.kt)

If both methods have metadata, everything is fine.

About


Languages

Language:Kotlin 100.0%