scalameta / metals

Scala language server with rich IDE features 🚀

Home Page:https://scalameta.org/metals/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

"could not find main class" error when assigning a key to "run" lense for a main class

kostaskougios opened this issue · comments

Describe the bug

The "run|debug" lense is a way to run your code, but this is tedious to use if you're editing anything other than the class with the @main method, and even if you're editing that it is better to have a keyboard shortcut to quickly run the code. So I added a keyboard shortcut but most of the time it doesn't work, especially when I finish editing some other class than the one with the main method. It starts the jvm but gets classnotfound error for the main class. I am not sure what happens there, it doesn't compile it? And even if it doesn't , if the code didn't change from a previous compilation, why would the class be missing?

To reproduce:

  • git clone https://github.com/kostaskougios/metals-bugs.git
  • import the project in vscode
  • assign Ctrl-F10 to "Rerun last task"
  • now open class "trymain" (it is a @main class that's why it is lowercase)
  • run it using the "run" lense, it should run fine.
  • open "Tank" class which is on a different module and edit it, i.e. add a "def x=5" at the end of it
  • press Ctrl-F10. It starts the jvm but with "Error: Could not find or load main class org.easygame.trymain"

Expected behavior

When pressing ^-F10 , trymain class should run normally.

Note the classfile for trymain is on the disk, so my guess is that the classpath is incorrect when the jvm starts.

Operating system

macOS

Editor/Extension

VS Code

Version of Metals

v1.35.5

Extra context or search terms

No response

Thanks for the report. I can't really reproduce that, it seems to work for me. However metals sends to VSCode the shell command java -classpath <...>.jar className and if you rerun the last task, the same shell command will be executed. So if e.g. the package changes it will fail, where the code lens will get updated with the new shell command. So maybe if you're trying to run it while compilation happens and the jar gets classfies get recreated this error occurs.

Ηι @kasiaMarek , I just tried again and it failed to run the main method when I pressed ^-F10. It fails even if I try after 1 minute, so it can't be compilation. One thing I didn't mention is that I am on JDK 21, maybe that's the issue? Also :

  • Executing task: /"opt"/"homebrew"/"Cellar"/"openjdk"/"21.0.3"/"libexec"/"openjdk.jdk"/"Contents"/"Home"/"bin"/"java" "-Duser.dir=/Users/kkougios/projects/metals-bugs/easygame-model" -classpath "/Users/kkougios/projects/metals-bugs/.metals/.tmp/classpath_2AFE4522EADD866D4F5B6F637B6F2479.jar" org.easygame.trymain

I can't find that classpath.jar file that metals is creating, I suppose it is deleted straight away.

Just to double check, did you:

  • run the trymain from the "run" lense (it works)
  • edited the Tank class, saved and then pressed ^-F10 (it fails to run trymain)

These is what I get when I do this locally:

 *  Executing task: /"opt"/"homebrew"/"Cellar"/"openjdk"/"21.0.3"/"libexec"/"openjdk.jdk"/"Contents"/"Home"/"bin"/"java" "-Duser.dir=/Users/kkougios/projects/metals-bugs/easygame-model" -classpath "/Users/kkougios/projects/metals-bugs/.metals/.tmp/classpath_2AFE4522EADD866D4F5B6F637B6F2479.jar" org.easygame.trymain  

Hi.
 *  Terminal will be reused by tasks, press any key to close it. 

 *  Executing task: /"opt"/"homebrew"/"Cellar"/"openjdk"/"21.0.3"/"libexec"/"openjdk.jdk"/"Contents"/"Home"/"bin"/"java" "-Duser.dir=/Users/kkougios/projects/metals-bugs/easygame-model" -classpath "/Users/kkougios/projects/metals-bugs/.metals/.tmp/classpath_2AFE4522EADD866D4F5B6F637B6F2479.jar" org.easygame.trymain  

Hi.
 *  Terminal will be reused by tasks, press any key to close it. 

 *  Executing task: /"opt"/"homebrew"/"Cellar"/"openjdk"/"21.0.3"/"libexec"/"openjdk.jdk"/"Contents"/"Home"/"bin"/"java" "-Duser.dir=/Users/kkougios/projects/metals-bugs/easygame-model" -classpath "/Users/kkougios/projects/metals-bugs/.metals/.tmp/classpath_2AFE4522EADD866D4F5B6F637B6F2479.jar" org.easygame.trymain  

Error: Could not find or load main class org.easygame.trymain
Caused by: java.lang.ClassNotFoundException: org.easygame.trymain

 *  The terminal process "/bin/zsh '-l', '-c', '/"opt"/"homebrew"/"Cellar"/"openjdk"/"21.0.3"/"libexec"/"openjdk.jdk"/"Contents"/"Home"/"bin"/"java" "-Duser.dir=/Users/kkougios/projects/metals-bugs/easygame-model" -classpath "/Users/kkougios/projects/metals-bugs/.metals/.tmp/classpath_2AFE4522EADD866D4F5B6F637B6F2479.jar" org.easygame.trymain '" failed to launch (exit code: 1). 
 *  Terminal will be reused by tasks, press any key to close it. 

 *  Executing task: /"opt"/"homebrew"/"Cellar"/"openjdk"/"21.0.3"/"libexec"/"openjdk.jdk"/"Contents"/"Home"/"bin"/"java" "-Duser.dir=/Users/kkougios/projects/metals-bugs/easygame-model" -classpath "/Users/kkougios/projects/metals-bugs/.metals/.tmp/classpath_2AFE4522EADD866D4F5B6F637B6F2479.jar" org.easygame.trymain  

Error: Could not find or load main class org.easygame.trymain
Caused by: java.lang.ClassNotFoundException: org.easygame.trymain

 *  The terminal process "/bin/zsh '-l', '-c', '/"opt"/"homebrew"/"Cellar"/"openjdk"/"21.0.3"/"libexec"/"openjdk.jdk"/"Contents"/"Home"/"bin"/"java" "-Duser.dir=/Users/kkougios/projects/metals-bugs/easygame-model" -classpath "/Users/kkougios/projects/metals-bugs/.metals/.tmp/classpath_2AFE4522EADD866D4F5B6F637B6F2479.jar" org.easygame.trymain '" failed to launch (exit code: 1). 
 *  Terminal will be reused by tasks, press any key to close it. 

 *  Executing task: /"opt"/"homebrew"/"Cellar"/"openjdk"/"21.0.3"/"libexec"/"openjdk.jdk"/"Contents"/"Home"/"bin"/"java" "-Duser.dir=/Users/kkougios/projects/metals-bugs/easygame-model" -classpath "/Users/kkougios/projects/metals-bugs/.metals/.tmp/classpath_2AFE4522EADD866D4F5B6F637B6F2479.jar" org.easygame.trymain  

Error: Could not find or load main class org.easygame.trymain
Caused by: java.lang.ClassNotFoundException: org.easygame.trymain

 *  The terminal process "/bin/zsh '-l', '-c', '/"opt"/"homebrew"/"Cellar"/"openjdk"/"21.0.3"/"libexec"/"openjdk.jdk"/"Contents"/"Home"/"bin"/"java" "-Duser.dir=/Users/kkougios/projects/metals-bugs/easygame-model" -classpath "/Users/kkougios/projects/metals-bugs/.metals/.tmp/classpath_2AFE4522EADD866D4F5B6F637B6F2479.jar" org.easygame.trymain '" failed to launch (exit code: 1). 
 *  Terminal will be reused by tasks, press any key to close it. 

Ok sorry I was able to open classpath_2AFE4522EADD866D4F5B6F637B6F2479.jar and see the manifest. It points to the correct classpath:

file:///Users/kkougios/projects/metals-bugs/.bloop/easygame-model/scala-3/classes/

So the path for the trymain is there but that folder is empty! Did bloop cleaned up the folder when compiling Tank class which is on world-model module? And why would it do that?

Just realized bloop uses it's own folder for classes, so the classes are there but still it doesn't run:

ls /Users/kkougios/projects/metals-bugs/.bloop/easygame-model/bloop-bsp-clients-classes/classes-Metals-bbJJWqVHT5KtHh6Gx3wOSA==/org/easygame
maths                  model                  trymain$package$.class trymain$package.class  trymain$package.tasty  trymain.class          trymain.tasty          ui                     view

This is very weird. It runs trymain OK when I press ^-F10 with "trymain" open in the editor but not if I open "Tank", edit it & save and press ^-F10. If I then switch back to "trymain" class in vscode and without changing it press ^-F10 it runs OK again.

Just realized bloop uses it's own folder for classes

Yep.

I'm still not able to reproduce this.

Screen.Recording.2024-06-07.at.13.17.56.mov

@kasiaMarek thanks for the video, seems you're doing the right thing but it works for you. You are using jdk21 and also are on macos, so this can't be it. Are you using metals "v1.35.5 (pre-release)" (the issue on my box used to happen with previous metals versions too)? Also I can't find the version of bloop.Server but it uses i.e. bloop-frontend_2.12-1.5.17.jar

I was able to find one more thing about this. The classpath.jar is inside a .tmp folder:
/Users/kkougios/projects/metals-bugs/.metals/.tmp

On my box, when I switch the vscode editor to trymain, the folder exists (and also ^-F10 works as expected). When I switch to Tank class, the folder still exists. If I edit the Tank class the folder gets deleted and the classpath.jar too. This means when it tries to run trymain, classpath.jar doesn't exist and it is silently ignored. Do you know what may case the .tmp folder to get deleted if I switch to the Tank class and change it (which is on a different module) ?

One more thing I noticed in the video is that when you added def x=5, it wasn't formatted with scalafmt. I assume you saved the file before ^-F10, but why it didn't format it? It should align the = to the one in def attached above it.

scalafmt is configured for the project and I guess it should work when you imported it.

but why it didn't format it?

I simply don't have auto format on save enabled.

Do you know what may case the .tmp folder to get deleted if I switch to the Tank class and change it (which is on a different module) ?

Not really, that seems odd. I can't see metals ever deleting this directory and the jars are only deleted on exit.

ok @kasiaMarek I see, I can't understand why it happens on my box only. I was digging a bit more into it. It seems when I edit the Tank class and save it, some module creates the "schemantic.db" directories inside .tmp/META-INF, and after doing some work it deletes them. Also something copies the src for the code there and then deletes it. But at the end it also deletes the classpath.jar as well as the .tmp folder. It maybe some other part of the code that does that, not necessarily the code responsible for the schemantic db but this is what I see when I change and save Tank class:

sudo fs_usage -w | grep '.metals/.tmp'

....

19:01:53.609036  mkdir                                  /Users/kkougios/projects/metals-bugs/.metals/.tmp/META-INF                                                                                                            0.000103   java.3124990
19:01:53.609108  mkdir                                  /Users/kkougios/projects/metals-bugs/.metals/.tmp/META-INF/semanticdb                                                                                                 0.000070   java.3124990
19:01:53.609163  mkdir                                  /Users/kkougios/projects/metals-bugs/.metals/.tmp/META-INF/semanticdb/world-model                                                                                     0.000053   java.3124990
19:01:53.609222  mkdir                                  /Users/kkougios/projects/metals-bugs/.metals/.tmp/META-INF/semanticdb/world-model/src                                                                                 0.000054   java.3124990
19:01:53.609275  mkdir                                  /Users/kkougios/projects/metals-bugs/.metals/.tmp/META-INF/semanticdb/world-model/src/main                                                                            0.000052   java.3124990
19:01:53.609327  mkdir                                  /Users/kkougios/projects/metals-bugs/.metals/.tmp/META-INF/semanticdb/world-model/src/main/scala                                                                      0.000051   java.3124990
19:01:53.609385  mkdir                                  /Users/kkougios/projects/metals-bugs/.metals/.tmp/META-INF/semanticdb/world-model/src/main/scala/world                                                                0.000057   java.3124990
19:01:53.609444  mkdir                                  /Users/kkougios/projects/metals-bugs/.metals/.tmp/META-INF/semanticdb/world-model/src/main/scala/world/model                                                          0.000058   java.3124990
19:01:53.609497  mkdir                                  /Users/kkougios/projects/metals-bugs/.metals/.tmp/META-INF/semanticdb/world-model/src/main/scala/world/model/tanks                                                    0.000052   java.3124990
19:01:53.621380  open              F=516      (_WC_T_______)  /Users/kkougios/projects/metals-bugs/.metals/.tmp/META-INF/semanticdb/world-model/src/main/scala/world/model/tanks/Tank.scala.semanticdb                        0.000173   java.3124990
...
19:01:53.660425  rmdir                                  /Users/kkougios/projects/metals-bugs/.metals/.tmp/META-INF/semanticdb                                                                                                 0.000032   java.3124990
...
**19:01:53.660552  unlink                                 /Users/kkougios/projects/metals-bugs/.metals/.tmp/classpath_7E9D9B8D4950DE7BF636312C8A4C99E4.jar                                                                      0.000070   java.3124990**
...
19:01:53.660786  rmdir                                  /Users/kkougios/projects/metals-bugs/.metals/.tmp/world-model/src/main/scala/world                                                                                    0.000031   java.3124990
...
19:01:53.660969  rmdir                                  /Users/kkougios/projects/metals-bugs/.metals/.tmp/world-model                                                                                                         0.000028   java.3124990
...
**19:01:53.661010  rmdir                                  /Users/kkougios/projects/metals-bugs/.metals/.tmp** 

Since this is the .metals tmp folder I would think it is the metals java process doing this. Maybe it is doing the deletion conditionally and it happens on my box only?

Okay, awesome. It gets deleted when we run scalafix (that's also when temp semanticdbs are stored in .tmp). Thanks for the analysis, it was very helpful. I'll push a fix tomorrow.

excellent, thanks @kasiaMarek , let me know how can I install the fix when it is ready, will it be a snapshot? For me this is important as I've to switch to sbt and back whenever I need to run my code.

let me know how can I install the fix when it is ready, will it be a snapshot?

It just got merged so it should be available in the next snapshot.

Thanks @kasiaMarek ,got the snapshot today and it all works well now!