What does kotlin.jvm.internal.Ref.*Ref do?

What’s the purpose of those *Ref types? What role do they play in the kotlin world?

I always see them when doing reverse-engineer, but there isn’t a single comment explaining their usages in the source code of kotlin, and Google only returns a bunch of java.lang.NoClassDefFoundError questions.

Have you got a specific example of what you’re talking about? I don’t really know what you’re referring to.

Class A{}
Class B{}
A a;
B b;
Ref$ObjectRef c;
c=a;
c=b;
a=(A)c;
b=(B)c;

something like that

Is that Kotlin code decompiled into Java or… ?

I’m guessing it’s something to do with using classes generated at runtime to hold any type, maybe.

Yeah, they are kotlin .class decompiled.

What does the Kotlin source code look like?

They are needed to provide a “mutable reference”. See this code:

fun foo() {
    var s = "hello"
    val r = Runnable { s = "world" }
}

We modify s in the lambda. It looks trivial from the source code perspective, but if we think for a second what’s happening there, we modified s from an entirely separate class, executed in a different context than foo, so how could it modify a local variable of foo? In this case the Kotlin compiler creates a thin wrapper over the string and passes it to the lambda. Lambda can modify the value stored inside the wrapper, and foo sees the change, because it also accesses the string through the wrapper. This wrapper is Ref$ObjectRef.

BTW, for the same reason a similar code in Java doesn’t compile:

public static void foo() {
    var s = "hello";
    var r = (Runnable) () -> {
        s = "world"; // doesn't compile
    };
}

Java disallow to modify variables belonging to outside scope inside closures. This is technically impossible to do without introducing some kind of a wrapper.

2 Likes

Huh, that’s really cool to know. I had wondered why Kotlin allows modifying external variables inside a lambda, when Java doesn’t.

1 Like