Title
t

Tasos Stamadianos

01/27/2019, 6:53 PM
Hi all, I've been getting an interesting error when my app runs for an extended period of time:
17:10:33.977 [main] ERROR bees.stream.MessageStream - [MessageStream.kt:42] || - Message deserialization failed.
kotlin.reflect.full.IllegalCallableAccessException: java.lang.IllegalAccessException: class kotlin.reflect.jvm.internal.calls.CallerImpl$Constructor cannot access a member of class bees.stream.MessageStream$SystemMessage with modifiers "public"
        at kotlin.reflect.jvm.internal.KCallableImpl.call(KCallableImpl.kt:224)
        at kotlin.reflect.jvm.internal.KCallableImpl.callDefaultMethod$kotlin_reflect_api(KCallableImpl.kt:152)
        at kotlin.reflect.jvm.internal.KCallableImpl.callBy(KCallableImpl.kt:110)
        at com.squareup.moshi.kotlin.reflect.KotlinJsonAdapter.fromJson(KotlinJsonAdapter.kt:104)
        at com.squareup.moshi.JsonAdapter$2.fromJson(JsonAdapter.java:137)
        at com.squareup.moshi.JsonAdapter.fromJson(JsonAdapter.java:41)
        at bees.stream.MessageStream.onMessages(MessageStream.kt:39)
        at bees.stream.kafka.KafkaConsumerProducerStream.start(KafkaProducerConsumerStream.kt:64)
        at bees.BeesKt.main(bees.kt:65)
Caused by: java.lang.IllegalAccessException: class kotlin.reflect.jvm.internal.calls.CallerImpl$Constructor cannot access a member of class bees.stream.MessageStream$SystemMessage with modifiers "public"
        at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:361)
        at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:591)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
        at kotlin.reflect.jvm.internal.calls.CallerImpl$Constructor.call(CallerImpl.kt:41)
        at kotlin.reflect.jvm.internal.KCallableImpl.call(KCallableImpl.kt:106)
        ... 8 common frames omitted
17:10:33.989 [main] DEBUG bees.stream.MessageStream - [MessageStream.kt:83] || - Completed message processing. Returning 0 responses.
I have a Moshi instance whose job it is to do this deserialization. The class it wants to create is:
private data class SystemMessage(val command: String, val sessionId: UUID, val commandId: UUID, val data: Any)
. This is private to the class within the module. This only happens when the app is running for longer periods, if I restart and try again it works fine. When I search "java cannot access a member of a class with modifiers public", I get results which indicate that the class cannot be instantiated since it's private to its enclosing class. However, this doesn't explain why it works for some time if I restart the app. I've tried with JVM 8 and JVM 11, same error on both. This was built with Kotlin 1.3.10, but I'm going to try 1.3.20 now. Any help would be greatly appreciated 🙂
r

robstoll

01/27/2019, 6:57 PM
I guess the error message is misleading and you access a private member (that's this issue: https://youtrack.jetbrains.com/issue/KT-18408)
t

Tasos Stamadianos

01/27/2019, 6:59 PM
It's attempting to access a public constructor in a private class, and curiously this only fails if the app is running for some time (> 5 hours)
i don't think it's running out of memory or anything, but I don't know enough about Kotlin or the JVM to diagnose further 😕
r

robstoll

01/27/2019, 7:00 PM
kotlin cannot access a constructor of a private class
regardless if the constructor is public or not
t

Tasos Stamadianos

01/27/2019, 7:01 PM
yes, that's exactly my suspicion. do you have any hunches as to why it works when the app freshly starts, but not after time?
r

robstoll

01/27/2019, 7:02 PM
Do you use lazy vals or similar and it does not get called when you start the app but only after some time due to some event?
It is also likely that Moshi lazily instantiates deserializers
t

Tasos Stamadianos

01/27/2019, 7:03 PM
We do not. To summarize our logic, we listen to messages from an Apache Kafka instance, and when one comes in its body is deserialized and then further logic is applied. It's this deserialization step that fails. If the program receives a message soon after starting (i have one running for about an hour and it still works ok), the deserialization step works fine. but after some time (overnight, so > 7h) it breaks
r

robstoll

01/27/2019, 7:04 PM
Are those messages all SystemMessages or do you usually receive a different kind? (I am only guessing)
t

Tasos Stamadianos

01/27/2019, 7:05 PM
they're all system messages. i'm testing with a dummy producer
Moshi also throws different errors if the data is malformed, missing, etc
r

robstoll

01/27/2019, 7:06 PM
Strange that it works sometimes, accessing a private class should always fail, any module-info.class in place?
d

Dico

01/27/2019, 7:08 PM
Kotlin can access constructors of a private class? As long as the class is in the same scope
t

Tasos Stamadianos

01/27/2019, 7:08 PM
@robstoll i don't see any
r

robstoll

01/27/2019, 7:09 PM
I am out of ideas then, sorry
t

Tasos Stamadianos

01/27/2019, 7:09 PM
@Dico the
SystemMessage
class is privately nested in a larger class
thank you for your help regardless 🙂 it's nbd to make the class public, I'll see where that gets me
d

David Hamilton

02/15/2022, 1:39 PM
@Tasos Stamadianos Seeing a very similar exception when load testing http4k/Jackson service. Did you ever establish what was the problem?
Seems there's something very weird happening with private (static) inner data classes.