In a Java shebang script I get this crazy error: can't find main(String[]) method in class: gomad.MyKotlin
and the 1st question I ask to myself is: "WHY on Earth does it look for the main()
method in that class?" (UPD Well, this does reproduce when java compiles-and-runs a single-file program.)
#!/usr/bin/java --source 11
package gomad;
import java.util.Arrays;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import static gomad.MyKotlin.*;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
int[] x = MyArrays.sorted(3, 14, 15, 92, 6, 53, 58, 97, 93, 2, 38, 4, 62, 6, 43);
System.out.println(Arrays.stream(x).boxed().collect(Collectors.toList()));
}
}
class MyKotlin { // the idea of also() comes from Kotlin
static <T> T also(T obj, Consumer<T> action) {
action.accept(obj);
return obj;
}
}
class MyArrays {
static int[] sorted(int ... xs) {
return also(xs, Arrays::sort);
}
}
In the case of this script, the message is error: can't find main(String[]) method in class: gomad.MyKotlin
.
When this program is run from IntelliJ Idea with she-bang commented out, everything works.
It is important to note that when this program is run as java Main.java
, the same senseless error: can't find main(String[]) method in class: gomad.MyKotlin
appears.
But If you try to run it as javac gomad/Main.java && java gomad.Main
, you get the expected result, no error.
$ /usr/lib/jvm/java-21-openjdk-amd64/bin/java Main.java
error: can't find main(String[]) method in class: gomad.MyKotlin
$ /usr/lib/jvm/java-21-openjdk-amd64/bin/java -version
openjdk version "21.0.2" 2024-01-16
OpenJDK Runtime Environment (build 21.0.2+13-Ubuntu-122.04.1)
OpenJDK 64-Bit Server VM (build 21.0.2+13-Ubuntu-122.04.1, mixed mode, sharing)
And this has nothing to do with Kotlin except that also()
is borrowed from Kotlin.
Folks, I know that this looks like a duplicate, but it isn’t. The other discussions say that the class with main()
must be declared first (which is true), and that one should use javac
then java
, which is not exactly how she-bang scripts work. This is Q&A-style and I post my solution along with this question. If you know why it happens and how it may be avoided without having to desist from using some language constructs, please contribute.
2
Answers
I do not know how to fix it, but I know a workaround. The workaround is: remove any static imports for local classes. Java seems to search for
main()
in the class mentioned in the first static import. So in this case if we remove:and replace
with
and then everything works (but becomes cumbersome).
There are more workarounds.
The 2nd workaround is rather a bad news. If you add the
main()
method to the class where Java says it expects to see it, it will work. At least, until the moment that your code changes so that Java will expect to findmain()
somewhere else.This abomination works:
And the 3rd workaround is to create a class with a reference to statically imported
main()
: