Tuesday, February 17, 2009

JDK 6 Supports * in Classpath But Be Aware of This

Finally JDK 6 (Mustang) lets me use wildcard (*) in classpath. I no longer have to enumerate all jar files in a lib directory. But with this added feature, it's easier to get errors like "javac: invalid flag:" For example, I want to complile a simple servlet, including all jar files in C:\Sun\AppServer\lib:

C:\tmp> javac -cp C:\Sun\AppServer\lib\*
HelloWorldServlet.java
javac: invalid flag: C:\Sun\AppServer\lib\addons
Usage: javac
use -help for a list of possible options
What's happening here is, the OS expands * to all files/directories in C:\Sun\AppServer\lib, since * has special meaning for the OS. So the real command resolves to:
javac -cp C:\Sun\AppServer\lib\activation.jar
C:\Sun\AppServer\lib\addon
C:\Sun\AppServer\lib\admin-cli.jar
C:\Sun\AppServer\lib\ant ... HelloWorldServlet.java
As all files/directories are expanded alphabetically, the first one (activation.jar) is treated as classpath element, and everything else starting with addon are treated as separate JVM options. Of course these are invalid JVM options, hence javac: invalid flag:

Note: if you are using javaw.exe instead of java.exe, * wildcard expansion in -cp or -classpath doesn't work, due to JDK 6 bug 6510337

So here are some tricks how to use * in classpath without getting burned:
  • Quote it, if your classpath has a single element that uses *. For example,
    javac -cp "C:\Sun\AppServer\lib\*" HelloWorldServlet.java
  • This problem doesn't exist if you have more than one element in classpath, even though they do not exist:
    javac -cp C:\Sun\AppServer\lib\*;\nosuchdir HelloWorldServlet.java
  • This problem exists for all JDK tools that takes classpath option, including java. The error is different but solution is the same as above.
    java -cp C:\temp\* A
    Exception in thread "main" java.lang.NoClassDefFoundError: C:\temp\b/jar
  • Of course, if the directory contains 1 jar file, it will be expanded correctly, and you don't need to quote it. But using * doesn't save you much typing:
    java -cp C:\single-jar-file-folder\* A
    this is A

No comments: