"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 classfies get recreated this error occurs.jar
gets
Ηι @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!