Once again, I was making good progress in my migration to Scala 3 (with a workaround to the problem that I posted about recently), and then I was hit with a NoSuchMethodError out of the blue. I tried several clean recompiles to no avail.
My program was working fine, and then I started playing around with some syntax changes just for fun (removing some optional braces), and I was hit with the NoSuchMethodError. The offending line is a simple case class instantiation that was working fine:
val options = TestOptions(args, numArgsReq=1)
Any idea what the problem might be? The stack trace follows. I see something about “reflect”. Is it possible that I am using some reflection that I am not ever aware of? If so, how can I track it down? Thanks.
java.lang.NoSuchMethodError: scala.runtime.ScalaRunTime$.wrapRefArray([Ljava/lang/Object;)Lscala/collection/immutable/ArraySeq;
at trajspec.test.TestOptions$.$lessinit$greater$default$2(TestOptions.scala:13)
at trajspec.test.Resolve1Test$.main(Resolve1Test.scala:28)
at trajspec.test.Resolve1Test.main(Resolve1Test.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at scala.reflect.internal.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:70)
at scala.reflect.internal.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31)
at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:101)
at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:70)
at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101)
at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22)
at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39)
at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29)
at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39)
at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:65)
at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:87)
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:98)
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
But there is a directory under that one, also called project (toplevel/project/project), which also contains a file called plugins.sbt containing this line:
OK, I reverted back to Scala 2.13.4, removed all target directories and did a clean compilation. Now I am still getting a NoSuchMethodError. What the hell could I have possibly done to screw this thing up so badly? This is getting ridiculous. Is it sbt 1.4.6 that is screwed up?
java.lang.NoSuchMethodError: scala.Product.$init$(Lscala/Product;)V
at trajspec.test.Resolve1Test$.(Resolve1Test.scala:24)
at trajspec.test.Resolve1Test.main(Resolve1Test.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at scala.reflect.internal.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:70)
at scala.reflect.internal.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31)
at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:101)
at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:70)
at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101)
at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22)
at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39)
at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29)
at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39)
at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:65)
at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:87)
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:98)
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
Yes, of course I use version control (git). I also routinely make defensive backups of my entire source directory in case I screw something up with git.
I just went back to my latest working version in Scala 2.13.4 and did a clean recompile. I am still getting a NoSuchMethodError:
At this point, it seems fairly clear to me that the problem is not with my source code but rather with my Scala/sbt setup. I even tried going back to sbt version 1.3.8, and that didn’t help.
At this point, I am basically dead in the water. Again I ask, what in the world could cause this problem and what can I do to solve it? Do I need to reinstall sbt? Thanks.
The stack trace seems to hint at trajspec.test.Resolve1Test being compiled against a different version of the Scala library than the code depending on it is eventually run against. How does this class enter your project (source code, managed/unmanaged lib,…), how is it compiled and against which Scala version (log output?), how is the app depending on it run and against which Scala library version (log output?, ideally including classpath),…?
I having been using a bash script to run my Scala programs and test drivers. It contains the following code:
cd ~/$project
sbt package
if [ $? != 0 ]; then exit $?; fi
sbt test:package
if [ $? != 0 ]; then exit $?; fi
CLASSPATH=`sbt --error 'set showSuccess := false' "export fullClasspath"`
export CLASSPATH=$CLASSPATH:~/$project/target/test-classes
This actually worked for years, but since I tried to migrate to Scala 3 it quit working. It’s probably not the best way of doing things, so what is the right way?
I see that sbt puts its compiled classes into toplevel/target, but there are several subdirectories and jar files in that target directory. Do I have to put those all on my CLASSPATH, or is there a simpler way? Thanks.
The first time I read this, it didn’t click. But I just reread it, and it hit me. The bash script that I use to run my test invokes scala – but a different version than sbt uses to compile! The scala version in my bash executable search path was not the one that sbt uses. Duh!
There are sbt plugins to package your application. GitHub - sbt/sbt-native-packager: sbt Native Packager is one Ive, but there might be better alternatives, or ways to use that to generate bash scripts only — for instance makeBashScript:
If you want to specify the main class to be run, use runMain instead of run.
Usually I’d expect test scope to contain tests without main methods and without any dependencies to external config, governed by a test framework, though.
My testing methods are perhaps a bit unconventional, but I am not a conventional software developer. Each of my test drivers is a case object with its own “main” method. I am willing to consider other ways, but for now I would just like to get the methods that I have been using for years to work.
All I need for now is a way to get access to the version of scala that sbt used to compile so I can invoke it in a bash script. Given the versatility of sbt, I would think there must be a command for that. Why can’t it just be “sbt scala”?
Then there’s likely no file with path $PROJECT_ROOT/src/test/scala/trajspec/test/Resolve1Test.scala (and neither $PROJECT_ROOT/src/main/scala/trajspec/test/Resolve1Test.scala) in your project…?
Build tools tend to rely heavily on conventions. You don’t have to comply with all of them (it makes life easier, though), but then it’s even more important to understand the expectations of the tool in order to bridge the gap between the tool’s conventions and yours.
sbt downloads and manages the Scala version(s) you have configured in your project. This is done via jar files, i.e. there are no “scala”/“scalac” executables for these.