jruby / jruby

JRuby, an implementation of Ruby on the JVM
https://www.jruby.org
Other
3.8k stars 924 forks source link

Named Kotlin companion object throws UndefinedMethod exception #6845

Open jonathanswenson opened 3 years ago

jonathanswenson commented 3 years ago

Environment Information

Provide at least:

(built from source from most recent commit on master: 4727fcb3b037537ceecc67d771aa338bd5188af4 using a simple nix derivation)

(glinux)

Expected Behavior

I’m checking out 9.3.0.0 with our application (upgrading from 9.2.16.0).

We load in a jar that is written (mostly) in kotlin.

There exsts some kotlin in the form:

class ClassName
  ...
  companion object CompanionObjectName {
    ...
  }
}

on 9.2.16.0, our application would reference this companion object via the syntax: com.x.y.ClassName.CompanionObjectName.create(...)

Actual Behavior

but after upgrading to 9.3.0.0 that threw an error: NoMethodError: undefined method `CompanionObjectName' for Java::ComXY::ClassName:Module

To get this to work I had to change to: com.x.y.ClassName::CompanionObjectName.create(...)

jonathanswenson commented 3 years ago

repro: (using gradle 6.8.3)

build with ./gradlew shadowJar to get kotlin runtime. run with jruby repro.rb

tree: omitted gradle wrappers

.
├── build.gradle.kts
├── repro.rb
├── settings.gradle.kts
└── src
    └── main
        └── kotlin
            └── com
                └── looker
                    └── foo
                        └── TestClass.kt

build.gradle.kts

plugins {
    id("org.jetbrains.kotlin.jvm") version "1.5.0"
    id("com.github.johnrengelman.shadow") version "6.1.0"
}

repositories {
    mavenCentral()
}

dependencies {
    implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
}

settings.gradle.kts

rootProject.name = "jruby_repro"

src/main/kotlin/com/looker/foo/TestClass.kt

package com.looker.foo

class TestClass {
  companion object TestCompanionObject {
    @JvmStatic
    fun doit() {
      println("done")
    }
  }
}

repro.rb

require_relative './build/libs/jruby_repro-all.jar'

# works
com.looker.foo.TestClass::TestCompanionObject.doit()
# throws NoMethodError: undefined method `NamedCompanionObject' for Java::ComLookerFoo::TestClass:Class
com.looker.foo.TestClass.NamedCompanionObject.doit()

Jar structure:

Archive:  build/libs/jruby_repro-all.jar
 Length   Method    Size  Cmpr    Date    Time   CRC-32   Name
--------  ------  ------- ---- ---------- ----- --------  ----
       0  Defl:N        2   0% 2021-09-20 20:20 00000000  META-INF/
      25  Defl:N       27  -8% 2021-09-20 20:15 ee027fb2  META-INF/MANIFEST.MF
      24  Defl:N       19  21% 2021-09-20 20:20 307d8f4d  META-INF/jruby_repro.kotlin_module
       0  Defl:N        2   0% 2021-09-20 20:15 00000000  com/
       0  Defl:N        2   0% 2021-09-20 20:15 00000000  com/looker/
       0  Defl:N        2   0% 2021-09-20 20:20 00000000  com/looker/foo/
     939  Defl:N      584  38% 2021-09-20 20:20 dc25e58b  com/looker/foo/TestClass.class
    1080  Defl:N      638  41% 2021-09-20 20:20 f31c20bf  com/looker/foo/TestClass$TestCompanionObject.class
     268  Defl:N      151  44% 1980-02-01 00:00 32baac7f  META-INF/kotlin-stdlib-jdk8.kotlin_module
       0  Defl:N        2   0% 2021-09-20 20:20 00000000  kotlin/
... load of kotlin classes from the kotlin runtime
headius commented 3 years ago

Could you turn this into an example repo? It might form the basis of a test kit for our Kotlin integration.

jonathanswenson commented 3 years ago

@headius what do you mean by / are you looking for in an example repo?