i think it turned out that the classpath length i had was too long for clj to launch a jvm on windows in some cases.
when the classpath got slightly shorter, clj would manage to launch a jvm, but then clj.native-image would try to launch native-image
with the classpath along with other options, causing the total command line length to exceed windows' limit.
i'm now checking lengths of classpaths for a variety of projects locally to see typical sizes.
for reference, the limitation on the length of the string for invoking the native-image command executed in cmd.exe (via a .bat file) as observed here is 7126 characters. one more character and i get the error:
The input line is too long.
The syntax of the command is incorrect.
the .cp file i had trouble with had file length 7517 bytes according to the properties dialog.
as a crude test, i looked at the lengths of the .cp files i could find on my system. there were 699 of them. of those, 115 had lengths that exceeded 7126 characters.
i guess that if the classpaths for those were used to try to launch a jvm on windows (via java's -cp argument as-is), many would end in the error above (native-image command invocation differs a bit from java.exe invocation, but perhaps it's close enough here).
assuming that's mostly correct, i think that puts it at about 16% (115 / 699) not able to be launched by clj on windows (due to the windows command line length limitations).
i've heard the number 8192 as the limit, so may be there's something off about what i'm doing -- but atm this situation doesn't seem like it's necessarily going to be that rare.The java
invocation in clojure
adds not only the .cp
file but also the .lib
file I think, and several of its own options.
Ah, just the name of the .lib
file...
exec "$JAVA_CMD" "${jvm_cache_opts[@]}" "${jvm_opts[@]}" "-Dclojure.libfile=$libs_file" -classpath "$cp" clojure.main "${main_cache_opts[@]}" "$@"
(from the Linux version -- the PS version will be similar)That total command line can only be 8K but it's going to include the full path to the java.exe
file, plus all of the above...
$JavaCmd @JvmCacheOpts @JvmOpts "-Dclojure.libfile=$LibsFile" -classpath $CP clojure.main @MainCacheOpts @ClojureArgs
(from the PS script so it's pretty similar)if it's cheap to test the java version and that's >= 9, one could use the @-file technique and put the classpath in a file instead of on the command line
I like this solution the most
for the java 8 case, the pathing jar approach appears to be implemented in tdeps 120.
iirc though the last survey suggested that java 8 is still quite prevalent
the pathing.jar approach might work, but apparently there are all sorts of "fun" limitations for the manifest file
https://github.com/taylorwood/clj.native-image/issues/18#issuecomment-559240320
i've looked at the code by timgilbert in TDEPS-120 (and lein-classpath-jar). as near as i can tell, the value it uses for the Class-Path: field in the manifest is a space-separate string of classpath elements. i am slightly surprised there are no problems with this, as i have read that there are a variety of constraints regarding lengths and formatting of values in a manifest file: https://stackoverflow.com/questions/3057841/too-long-line-in-manifest-file-while-trying-to-create-jar/3057862
it would be great if the current code works well as it certainly seems simpler than having to jump through the extra hoops that people seem to have (cf. the stackoverflow link).
perhaps the Attribute class' put method "does the right thing". that would be great.
i guess i can try generating a pathing jar with timgilbert's code and look at the content of the manifest file :)
(i guess it's more likely that it's a different method that "does the right thing")
What if the jar has a space in the path?
perhaps i can test to find out
ok, i haven't tested the space in path thing yet, but i have examined a created pathing-jar's manifest.mf: https://pastebin.com/GkppSCnw
file: uris are used, so may be spaces will end up as %20
line lengths do appear to be about 72 chars as the jar spec says
the leading space on the subsequent lines is for continuation afaict
i tried putting a space in an element of the classpath and generating the pathing jar. as expected, a %20
showed up in the Class-Path: field's value.
when the pathing jar code is run on a linux box with windows file paths, the resulting file: uris are a bit wonky, but when run on a windows box, they seem ok: https://pastebin.com/qUEW7xYL
here's the wonky stuff: https://pastebin.com/EZs47wNU
may be that's not too surprising