I have a simple interface and its implementation:
interface Iface {
fun doSomething(s: String)
}
class IfaceImpl : Iface {
override fun doSomething(s: String) {
println("Doing the job, s = $s")
}
}
Also, there are two identical (at least I cannot spot the difference) invocation handlers, one in Java and one in Kotlin:
public class JavaHandler implements InvocationHandler {
private final Iface target;
public JavaHandler(Iface target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Java handler works");
return method.invoke(target, args);
}
}
class KotlinHandler(private val target: Iface) : InvocationHandler {
override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any {
println("Kotlin proxy works")
return method!!.invoke(target, args)
}
}
They both just output some string and then invoke the method on the target.
Finally, here is the code I run:
fun main(args: Array<String>) {
val target = IfaceImpl()
target.doSomething("one")
val javaProxy = newProxy(JavaHandler(target))
javaProxy.doSomething("two")
val kotlinProxy = newProxy(KotlinHandler(target))
kotlinProxy.doSomething("three")
}
fun newProxy(handler: InvocationHandler): Iface {
return Proxy.newProxyInstance(Iface::class.java.classLoader, arrayOf(Iface::class.java), handler) as Iface
}
It creates two java proxies, using both invocation handlers, and tries to exercise them.
Java handler works fine, but Kotlin handler does not. The output follows:
Doing the job, s = one
Java handler works
Doing the job, s = two
Kotlin proxy works
Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at KotlinHandler.invoke(KotlinHandler.kt:12)
at com.sun.proxy.$Proxy0.doSomething(Unknown Source)
at TestKt.main(Test.kt:17)
I can see with a debugger that in both cases args
consists of 1 element, and it's a java.lang.Integer
instance.
An interesting thing is that if the method has 0 parameters, the error message is different:
Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
In such a case, null
is passed as args
parameter (which is allowed by javadocs for parameterless calls).
Do I do something wrong? Or is this a bug?
My build.gradle has the following:
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.2.61'
}