I want to run java code from the command line, and I don't understand why I manage to do that from within the folder holding the code, but not from another folder. I am on Windows and am using Cygwin.
The folder /usr/local/lib/mytoolfolder/
contains two folders with java code:
mytool/
(containing the class I want to run)utils/
(containing dependencies)If I do
$ cd /usr/local/lib/mytoolfolder/
$ java -cp ".;utils/bin;utils/lib/*;mytool/bin;mytool/lib/*" mytool.MyTool
... the class MyTool
is called without any problems, and I get the expected output.
If I cd
to a random other folder on my computer and try to call MyTool
again, now including the full paths in the class path, like so:
$ java -cp "/usr/local/lib/mytoolfolder/.;/usr/local/lib/mytoolfolder/utils/bin;/usr/local/lib/mytoolfolder/utils/lib/*;/usr/local/lib/mytoolfolder/mytool/bin;/usr/local/lib/mytoolfolder/mytool/lib/*" mytool.MyTool
... I get this ClassNotFoundException
:
Error: Could not find or load main class mytool.MyTool
Caused by: java.lang.ClassNotFoundException: mytool.MyTool
I have checked that the classpaths are correct and I have checked permissions.
I understand that this error means that java can't find the class (obviously). I assume that this is because there is something wrong with the classpath (as Example 1 rules out that there is something wrong with the code itself).
I don't understand WHAT is wrong with the classpath, or with this approach. Where is the flaw in my logic? And how can I make it work?
Additional tips to debug this further are also appreciated.
As requested by g00se
below -- the output of find /usr/local/lib/mytoolfolder -name \*.jar -o -name \*.class
looks like this (the actual output contains more of the same because my example above is minimised):
/usr/local/lib/mytoolfolder/mytool/bin/mytool/MyTool$Connection.class
/usr/local/lib/mytoolfolder/mytool/bin/mytool/MyTool.class
/usr/local/lib/mytoolfolder/utils/bin/tools/math/StatUtils.class
/usr/local/lib/mytoolfolder/utils/bin/tools/path/PathTools$1.class
/usr/local/lib/mytoolfolder/utils/bin/tools/path/PathTools.class
...
/usr/local/lib/mytoolfolder/utils/bin/tools/text/StringTools.class
/usr/local/lib/mytoolfolder/utils/bin/tools/ToolBox.class
/usr/local/lib/mytoolfolder/utils/bin/tools/ToolBox.class
/usr/local/lib/mytoolfolder/utils/lib/jackson-annotations-2.17.1.jar
/usr/local/lib/mytoolfolder/utils/lib/jackson-core-2.17.1.jar
/usr/local/lib/mytoolfolder/utils/lib/jackson-databind-2.17.1.jar
java
is a Windows program so it doesn't understand Unix-style paths. Cygwin comes with a utility, cygpath
that will convert paths, either individually, or even an entire PATH-style path, with the -p
switch. But, it expects such a path to be delimited by colons. It will turn it into a Windows-style semicolon-delimited path.
So you could use:
cygpath -pw "/usr/local/lib/mytoolfolder:/usr/local/lib/mytoolfolder/utils/bin:/usr/local/lib/mytoolfolder/utils/lib/*:/usr/local/lib/mytoolfolder/mytool/bin:/usr/local/lib/mytoolfolder/mytool/lib/*"
to convert the path, or even:
java -cp "$(cygpath -pw '/usr/local/lib/mytoolfolder:/usr/local/lib/mytoolfolder/utils/bin:/usr/local/lib/mytoolfolder/utils/lib/*:/usr/local/lib/mytoolfolder/mytool/bin:/usr/local/lib/mytoolfolder/mytool/lib/*")" mytool.MyTool
to run your program.