scala / scala3

The Scala 3 compiler, also known as Dotty.
https://dotty.epfl.ch
Apache License 2.0
5.87k stars 1.06k forks source link

java.lang.IllegalAccessError: failed to access class com.linecorp.armeria.server.AbstractContextPathServicesBuilder #21797

Open chungonn opened 1 week ago

chungonn commented 1 week ago

Compiler version

Scala version 3.3.3 and 3.5.1

Minimized code

The code below runs in Java. But in Scala, it throws an IllegalAccessError exception.

package experiment

import com.linecorp.armeria.common.HttpResponse
import com.linecorp.armeria.server.Server

@main def hello(): Unit =
  val server = Server.builder()
    .contextPath("/v1")
    .service("/", (ctx, req) => HttpResponse.of("Hello, world"))
    .and()
    .build()
    .start()

  println(s"server started = ${server}")

build.sbt

val scala3Version = "3.5.1"

lazy val root = project
  .in(file("."))
  .settings(
    name := "test-armeria",
    version := "0.1.0-SNAPSHOT",

    scalaVersion := scala3Version,

    libraryDependencies ++= Seq(
      "com.linecorp.armeria" % "armeria" % "1.30.1",
    )
  )

Output

Exception in thread "main" java.lang.IllegalAccessError: failed to access class com.linecorp.armeria.server.AbstractContextPathServicesBuilder from class experiment.Main$package$ (com.linecorp.armeria.server.AbstractContextPathServicesBuilder and experiment.Main$package$ are in unnamed module of loader 'app')
    at experiment.Main$package$.hello(Main.scala:9)
    at experiment.hello.main(Main.scala:6)

Expectation

The code should run without error.

chungonn commented 1 week ago

The same code works in Scala 2.12.13

package experiment

import com.linecorp.armeria.common.HttpResponse
import com.linecorp.armeria.server.Server
object Test {

  def main(args: Array[String]): Unit = {
    val server = Server.builder()
      .contextPath("/v1")
      .service("/", (ctx, req) => HttpResponse.of("Hello, world"))
      .and()
      .build()
      .start()

    println(s"server started = ${server}")
  }
}
val scala3Version = "2.12.13"

lazy val root = project
  .in(file("."))
  .settings(
    name := "test-armeria",
    version := "0.1.0-SNAPSHOT",

    scalaVersion := scala3Version,

    libraryDependencies ++= Seq(
      "com.linecorp.armeria" % "armeria" % "1.30.1",
    )
  )
Gedochao commented 1 week ago

This seems to have been fixed in nightly (3.6.1-RC1-bin-20241016-2fc299b-NIGHTLY), but not in 3.5.2-RC2. We might need to bisect the fix and backport to the LTS. cc @prolativ

The following works:

//> using scala 3.6.1-RC1-bin-20241016-2fc299b-NIGHTLY
//> using dep com.linecorp.armeria:armeria:1.30.1
package experiment

import com.linecorp.armeria.common.HttpResponse
import com.linecorp.armeria.server.Server
object Test {

  def main(args: Array[String]): Unit = {
    val server = Server.builder()
      .contextPath("/v1")
      .service("/", (ctx, req) => HttpResponse.of("Hello, world"))
      .and()
      .build()
      .start()

    println(s"server started = ${server}")
  }
}
chungonn commented 1 week ago

@Gedochao I confirmed that 3.6.1-RC1-bin-20241016-2fc299b-NIGHTLY fixes the problem

chungonn commented 1 week ago

I would be grateful if this fixed can be backport to the next possible 3.5.x. Thanks in advance

Gedochao commented 1 week ago

I would be grateful if this fixed can be backport to the next possible 3.5.x. Thanks in advance

It's likely too late for it to be backported to 3.5.2, unless we'd have another RC. which I'm hoping we won't as 3.5.2 (the last in the 3.5.x line) is being released as we speak. See:

tagging @WojciechMazur just in case. Otherwise, I'm guessing the fix would be included in 3.6.0 or 3.6.1

chungonn commented 1 week ago

Noted with thanks!

WojciechMazur commented 1 week ago

3.5.2 final has already been shipped. It will be backported to 3.6.0 or 3.6.1

prolativ commented 1 week ago

I needed to slightly modify the snippet to close the server so that it doesn't hang the bisecting tests. /tmp/bisect/ArmeriaServer.scala:

//> using dep com.linecorp.armeria:armeria:1.30.1

import com.linecorp.armeria.common.HttpResponse
import com.linecorp.armeria.server.Server
object Test {
  def main(args: Array[String]): Unit = {
    val server = Server.builder()
      .contextPath("/v1")
      .service("/", (ctx, req) => HttpResponse.of("Hello, world"))
      .and()
      .build()
    println(s"starting server")
    val started = server.start()
    started.get()
    println(s"server started")
    server.stop()
    println(s"server stopped")
  }
}

Bisected with

scala-cli project/scripts/bisect.scala -- --should-fail --releases 3.5.1-RC1-bin-20240628-1efbb92-NIGHTLY... run /tmp/bisect/ArmeriaServer.scala

The bisect points to https://github.com/scala/scala3/pull/21362

WojciechMazur commented 1 week ago

Ah, I've just bisected it to the same commit, adding sys.exit(0) would do the job as well for bisect purpose. I'll start backporting this to 3.6.0-RC1. I propose to close it after backporting to 3.3.5 LTS

prolativ commented 1 week ago

@WojciechMazur as far as I can see the issue was fixed on 10.08, which was before the cut-off of release-3.6.0, so this shouldn't need any backporting for 3.6.x. Or did I miss something?

WojciechMazur commented 1 week ago

That's correct, I've just checked to ensure it's included, so no work needed for Next release