H2ONaCl
H2ONaCl

Reputation: 11279

java classpath wildcard behaviour

I've used the java -classpath wildcard expansion feature previously and successfully. I'm currently experiencing a strange problem with it.

The wildcard is supposed to expand to every jar in the named folder. Here's a quote from Oracle:

Class path entries can contain the basename wildcard character *, 
which is considered equivalent to specifying a list of all the files 
in the directory with the extension .jar or .JAR. For example, the 
class path entry foo/* specifies all JAR files in the directory 
named foo. A classpath entry consisting simply of * expands to a 
list of all the jar files in the current directory.

This is a link to Oracle doc on Java 6 on the subject of classpath.

The behaviour I am seeing contradicts this. Here are 3 runs. The first explicitly names the jar and so it works. The others use a wildcard and fail. Why? This matters to me because I rely on wildcards (elsewhere) and so an understanding of this unexpected behaviour is important to me.

#!/bin/bash

printf "The EV is...\n"
echo $CLASSPATH
printf "The working directory is...\n"
pwd
printf "Directory listing...\n"
ls 
printf "END of directory listing.\n"

printf "Test with named jar.\n"
java -javaagent:../sizeof/sizeof.jar -classpath ./testsizeof.jar info.zqxj.test.Tester

printf "Test with star.\n"
java -javaagent:../sizeof/sizeof.jar -classpath * info.zqxj.test.Tester

printf "Test with dot slash star.\n"
java -javaagent:../sizeof/sizeof.jar -classpath ./* info.zqxj.test.Tester

The output:

The EV is...

The working directory is...
/home/b/Documents/workspace/testsizeof
Directory listing...
bin  run.sh  src  testsizeof.jar
END of directory listing.
Test with named jar.
40
Test with star.
Exception in thread "main" java.lang.NoClassDefFoundError: run/sh
Caused by: java.lang.ClassNotFoundException: run.sh
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
Could not find the main class: run.sh.  Program will exit.
Test with dot slash star.
Exception in thread "main" java.lang.NoClassDefFoundError: //run/sh
Caused by: java.lang.ClassNotFoundException: ..run.sh
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
Could not find the main class: ./run.sh.  Program will exit.

Upvotes: 3

Views: 4413

Answers (1)

H2ONaCl
H2ONaCl

Reputation: 11279

Solution, double quote the classpath argument. Example: -classpath "*" This is necessary on the command line as well as inside a bash script.

A subsequent addendum:

Furthermore, note that -classpath "~/folder/*" fails but -classpath ~/folder/"*" is good. Quote the wildcard but do not quote the ~. It seems that you need the operating system to interpret ~ but you need to quote the * wildcard because you want to pass it to java for expansion in Java-fashion.

Note also that you should not ask java to expand *.jar because that will have an unintended result. The Java spec says that the correct wildcard is just the * alone.

Upvotes: 7

Related Questions