Thread.currentThread.getContextClassLoader
Thread.currentThread.getContextClassLoader.getParent
classOf[Person].getClassLoader
classOf[Person].getClassLoader.loadClass("Person")```
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```
The REPLs generally perform two tricks to provide a âseamlessâ experience: your code is packaged for purposes of managing namespaces or just to put your definitions into a class; and when output is displayed, all evidence of packaging is stripped as mere noise or an implementation detail.
Welcome to Scala 2.13.10 (OpenJDK 64-Bit Server VM, Java 19).
Type in expressions for evaluation. Or try :help.
scala> case class Person(name: String)
class Person
scala> classOf[Person].getName
val res0: String = Person
scala> classOf[Person].getName.toUpperCase
val res1: String = $LINE3.$READ$$IW$PERSON
scala> classOf[Person].getClassLoader.loadClass("$line3.$read$$iw$Person")
val res2: Class[_] = class Person
similarly
Welcome to Scala 3.2.1 (19, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
scala> case class Person(name: String)
// defined case class Person
scala> classOf[Person].getName
val res0: String = Person
scala> classOf[Person].getName.toUpperCase
val res1: String = RS$LINE$1$PERSON
scala> classOf[Person].getClassLoader.loadClass("rs$line$1$Person")
java.lang.LinkageError: loader dotty.tools.repl.AbstractFileClassLoader @2fa3be26 attempted duplicate class definition for rs$line$1$Person. (rs$line$1$Person is in unnamed module of loader dotty.tools.repl.AbstractFileClassLoader @2fa3be26, parent loader java.net.URLClassLoader @6d868997)
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1013)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:875)
at dotty.tools.repl.AbstractFileClassLoader.findClass(AbstractFileClassLoader.scala:54)
at dotty.tools.repl.AbstractFileClassLoader.loadClass(AbstractFileClassLoader.scala:57)
... 33 elided
Thatâs the result I would expect, Iâm not sure what Scala 2 does differently.
I think the class loader could support âname translationâ in the reflection API, as a convenience.
In general, I think the REPL should provide all the conveniences. For example, it used to make it easier to dump javap output for functions, including anonymous functions. Since the REPL knows the underlying compiler intimately, it can serve as a guide through its labyrinthine ramifications, much like Virgil for Dante.
In Scala 2, you can also use raw paste mode if having a human readable or predictable class name is important for some reason.
scala> :paste -raw
// Entering paste mode (ctrl-D to finish)
case class Person(name: String)
// Exiting paste mode, now interpreting.
scala> classOf[Person].getClassLoader.loadClass("Person")
res0: Class[_] = class Person
REPL should allow to create class and load them dynamically, I am trying with Scala 2.12.10 with JDK 11.0.16
Welcome to Scala 2.12.10 (OpenJDK 64-Bit Server VM, Java 11.0.16).
Type in expressions for evaluation. Or try :help.
scala> case class Person(name: String)
defined class Person
scala> classOf[Person].getName
res0: String = Person
scala> classOf[Person].getName.toUpperCase
res1: String = $LINE3.$READ$$IW$$IW$PERSON
scala> classOf[Person].getClassLoader.loadClass("$LINE3.$READ$$IW$$IW$PERSON")
java.lang.ClassNotFoundException: $LINE3.$READ$$IW$$IW$PERSON
at scala.reflect.internal.util.AbstractFileClassLoader.findClass(AbstractFileClassLoader.scala:72)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
... 28 elided
scala> classOf[Person].getClassLoader.loadClass(classOf[Person].getName)
res8: Class[_] = class Person
scala> println(res8)
class $line2.$read$$iw$$iw$Person
The reason that you see res8: Class[_] = class Person is that the REPL tries to hide those $line2.$read$$iw$$iw$ internals from the user.
Actually it was an easy fix, REPL already uses a classloader that translates the funny name, but defineClass complains if the name in the class data doesnât match the name you think it should be.