Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scala REPL (Shell) throws NoClassDefFoundError #12705

Closed
sethiaarun opened this issue Dec 21, 2022 · 6 comments · Fixed by scala/scala#10253
Closed

Scala REPL (Shell) throws NoClassDefFoundError #12705

sethiaarun opened this issue Dec 21, 2022 · 6 comments · Fixed by scala/scala#10253
Assignees
Milestone

Comments

@sethiaarun
Copy link

Reproduction steps

Scala version: 2.12.10

case class Person(name:String)

Thread.currentThread.getContextClassLoader
Thread.currentThread.getContextClassLoader.getParent
classOf[Person].getClassLoader
classOf[Person].getClassLoader.loadClass("Person")

Problem

Running this code from Scala REPL (Shell) throws NoClassDefFoundError

java.lang.NoClassDefFoundError: Person (wrong name: Person)
  at java.base/java.lang.ClassLoader.defineClass1(Native Method)
  at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
  at scala.reflect.internal.util.AbstractFileClassLoader.findClass(AbstractFileClassLoader.scala:74)
  at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
  at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
  ... 28 elided
@SethTisue
Copy link
Member

SethTisue commented Dec 21, 2022

This isn't a bug. Please use https://users.scala-lang.org for questions, or see https://scala-lang.org/community for other options.

@scala scala locked as off-topic and limited conversation to collaborators Dec 21, 2022
@som-snytt
Copy link

dotty says

scala> classOf[Person].getClassLoader.loadClass("Person")
java.lang.ClassNotFoundException: Person
  at dotty.tools.repl.AbstractFileClassLoader.findClass(AbstractFileClassLoader.scala:51)
  at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
  at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
  at dotty.tools.repl.AbstractFileClassLoader.loadClass(AbstractFileClassLoader.scala:57)
  ... 33 elided

java.lang.NoClassDefFoundError: Person (wrong name: Person) is interesting but not sure about the implication for java reflection.

@SethTisue
Copy link
Member

@som-snytt
Copy link

som-snytt commented Jan 3, 2023

Actually "it should just work".

scala> case class Person(name: String)
class Person

scala> $intp.classLoader.getResource("Person.class")
val res0: java.net.URL = memory:(memory)/Person.class

scala> $intp.classLoader.classBytes("Person")
val res1: Array[Byte] = Array(-54, -2, -70, -66, 0, 0, 0, 52, 0, 111, 1, 0, 23, 36, 108, 105, 110, 101, 51, 47, 36, 114, 101, 97, 100, 36, 36, 105, 119, 36, 80, 101, 114, 115, 111, 110, 7, 0, 1, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 7, 0, 3, 1, 0, 13, 115, 99, 97, 108, 97, 47, 80, 114, 111, 100, 117, 99, 116, 7, 0, 5, 1, 0, 20, 106, 97, 118, 97, 47, 105, 111, 47, 83, 101, 114, 105, 97, 108, 105, 122, 97, 98, 108, 101, 7, 0, 7, 1, 0, 9, 60, 99, 111, 110, 115, 111, 108, 101, 62, 1, 0, 16, 36, 108, 105, 110, 101, 51, 47, 36, 114, 101, 97, 100, 36, 36, 105, 119, 7, 0, 10, 1, 0, 12, 36, 108, 105, 110, 101, 51, 47, 36, 114, 101, 97, 100, 7, 0, 12, 1, 0, 3, 36, 105, 119, 1, 0, 6, 80, 101, 114, 115, 111, 110, 1, 0, 4, 110, 97...

scala> $intp.classLoader.loadClass("Person")
java.lang.NoClassDefFoundError: Person (wrong name: Person)
  at java.base/java.lang.ClassLoader.defineClass1(Native Method)
  at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1013)
  at scala.reflect.internal.util.AbstractFileClassLoader.findClass(AbstractFileClassLoader.scala:77)
  at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
  at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
  ... 30 elided

The problem is that it goes to defineClass and supplies the name, which doesn't match the "translated" name in the class file data.

@som-snytt som-snytt reopened this Jan 3, 2023
@SethTisue
Copy link
Member

SethTisue commented Jan 3, 2023

note that this works as expected:

scala 2.13.10> case class Person(name:String)
class Person

scala 2.13.10> println(classOf[Person])
class $line7.$read$$iw$Person

scala 2.13.10> classOf[Person].getClassLoader.loadClass("$line3.$read$$iw$Person")
val res4: Class[_] = class Person

I don't understand why you think .loadClass("Person") should work, or how it could be made to work?

@som-snytt
Copy link

som-snytt commented Jan 3, 2023

See the PR. It finds the class data, but the name doesn't match. (This is the point of the TranslatingClassLoader. I did not check whether the behavior changed at some point; there are other JDK version issues for AbstractFileClassLoader to address, too.)

@scala scala unlocked this conversation Jan 3, 2023
@SethTisue SethTisue added this to the 2.13.11 milestone Jan 3, 2023
@SethTisue SethTisue added the repl label Jan 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants