It seems I've encountered a weird problem with interaction of java reflection API (particularly, java.lang.reflect.Proxy and kotlin.time.Duration. It looks like Java Reflection fails to determine method return type for kotlin.time.Duration
. Consider the following example:
@file:JvmName("Main")
package org.test.kotlin.time.duration
import java.lang.reflect.Proxy
import kotlin.time.Duration
import kotlin.time.ExperimentalTime
import kotlin.time.seconds
@ExperimentalTime
interface I {
fun getNullableDuration(): Duration? = 1.seconds
fun getRange(): IntRange = 1..3
fun getDuration(): Duration = 1.seconds
}
class IC: I
inline fun <reified T> T.sampleProxy(): T = sampleProxy(T::class.java)
fun <T> sampleProxy(c: Class<T>): T {
return c.cast(Proxy.newProxyInstance(c.classLoader, arrayOf(c)) { _, method, _ ->
println("[proxy] ${method.declaringClass.name}::${method.name} return type is ${method.returnType}")
when (method.name) {
"getNullableDuration", "getDuration" -> 1.seconds
"getRange" -> 0..1
else -> TODO("method ${method.name} isn't handled yet")
}
})
}
fun main() {
val v: I = IC()
println("I::getNullableDuration() return type is ${v::getNullableDuration.returnType}")
v.sampleProxy().getNullableDuration()
println("I::getRange() return type is ${v::getRange.returnType}")
v.sampleProxy().getRange()
println("I::getDuration() return type is ${v::getDuration.returnType}")
v.sampleProxy().getDuration()
}
This code produces the following output:
I::getNullableDuration() return type is kotlin.time.Duration?
[proxy] org.test.kotlin.time.duration.I::getNullableDuration return type is class kotlin.time.Duration
I::getRange() return type is kotlin.ranges.IntRange
[proxy] org.test.kotlin.time.duration.I::getRange return type is class kotlin.ranges.IntRange
I::getDuration() return type is kotlin.time.Duration
[proxy] org.test.kotlin.time.duration.I::getDuration return type is double
Exception in thread "main" java.lang.ClassCastException: class kotlin.time.Duration cannot be cast to class java.lang.Double (kotlin.time.Duration is in unnamed module of loader 'app'; java.lang.Double is in module java.base of loader 'bootstrap')
at com.sun.proxy.$Proxy2.getDuration(Unknown Source)
at org.test.kotlin.time.duration.Main.main(main.kt:38)
at org.test.kotlin.time.duration.Main.main(main.kt)
Process finished with exit code 1
As one can see, inside sampleProxy
return types for getNullableDuration()
and getRange()
are determined correctly (kotlin.time.Duration?
expectedly becomes kotlin.time.Duration
), while getDuration()
suddenly becomes a method returning double
and the cast from kotlin.time.Duration to double on return from the method fails with the exception.
What could be a reason for the problem? How can I workaround it?
My environment:
- OpenJDK 11.0.6+10
- Kotlin 1.3.71
- Linux/x86-64
Aucun commentaire:
Enregistrer un commentaire