United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 7146424 Wildcard expansion for single entry classpath
7146424 : Wildcard expansion for single entry classpath

Details
Type:
Bug
Submit Date:
2012-02-16
Status:
Resolved
Updated Date:
2013-05-06
Project Name:
JDK
Resolved Date:
2012-08-10
Component:
tools
OS:
windows_2008,windows_xp,windows_7,windows
Sub-Component:
launcher
CPU:
x86,generic
Priority:
P2
Resolution:
Fixed
Affected Versions:
7,7u6
Fixed Versions:
8

Related Reports
Backport:
Backport:
Backport:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Relates:
Relates:
Relates:
Relates:

Sub Tasks

Description
FULL PRODUCT VERSION :
java version "1.7.0_03"
Java(TM) SE Runtime Environment (build 1.7.0_03-b05)
Java HotSpot(TM) Client VM (build 22.1-b02, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
Wildcard expansion doesn't work correctly for -classpath (-cp) parameter when only one entry is specified.


REGRESSION.  Last worked in version 6u29

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Script (batch file) for running the test:

mkdir lib
javac test/*.java
jar cvf lib/a.jar test/A.class
jar cvf lib/b.jar test/B.class
java -cp "lib/*" test.B


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Following message should be on the output:

main() in class B executed

ACTUAL -
Following message appears on the output:

Error: Could not find or load main class lib.b.jar

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Java launcher debug info when it doesn't work:

----_JAVA_LAUNCHER_DEBUG----
Launcher state:
        debug:on
        javargs:off
        program name:java
        launcher name:java
        javaw:off
        fullversion:1.7.0_03-b05
        dotversion:1.7
        ergo_policy:DEFAULT_ERGONOMICS_POLICY
Command line args:
argv[0] = java
argv[1] = -cp
argv[2] = lib/a.jar
argv[3] = lib/b.jar
argv[4] = test.B
JRE path is c:\Program Files\Java\jre7
jvm.cfg[0] = ->-client<-
jvm.cfg[1] = ->-server<-
jvm.cfg[2] = ->-hotspot<-
    name: -hotspot  vmType: VM_ALIASED_TO  alias: -client
jvm.cfg[3] = ->-classic<-
jvm.cfg[4] = ->-native<-
jvm.cfg[5] = ->-green<-
8371 micro seconds to parse jvm.cfg
Default VM: client
JVM path is c:\Program Files\Java\jre7\bin\client\jvm.dll
JRE path is c:\Program Files\Java\jre7
CRT path is c:\Program Files\Java\jre7\bin\msvcr100.dll
8795 micro seconds to LoadJavaVM
JavaVM args:
    version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 5
    option[ 0] = '-Dsun.java.launcher.diag=true'
    option[ 1] = '-Djava.class.path=.'
    option[ 2] = '-Djava.class.path=lib/a.jar'
    option[ 3] = '-Dsun.java.command=lib/b.jar test.B'
    option[ 4] = '-Dsun.java.launcher=SUN_STANDARD'
59450 micro seconds to InitializeJVM
Main class is 'lib/b.jar'
App's argc is 1
    argv[ 0] = 'test.B'
Error: Could not find or load main class lib.b.jar
java.lang.ClassNotFoundException: lib.b.jar
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)


Java launcher debug info when it works:

----_JAVA_LAUNCHER_DEBUG----
Launcher state:
	debug:on
	javargs:off
	program name:java
	launcher name:java
	javaw:off
	fullversion:1.7.0_03-b05
	dotversion:1.7
	ergo_policy:DEFAULT_ERGONOMICS_POLICY
Command line args:
argv[0] = java
argv[1] = -cp
argv[2] = lib/*;
argv[3] = test.B
JRE path is c:\Program Files\Java\jre7
jvm.cfg[0] = ->-client<-
jvm.cfg[1] = ->-server<-
jvm.cfg[2] = ->-hotspot<-
    name: -hotspot  vmType: VM_ALIASED_TO  alias: -client
jvm.cfg[3] = ->-classic<-
jvm.cfg[4] = ->-native<-
jvm.cfg[5] = ->-green<-
322 micro seconds to parse jvm.cfg
Default VM: client
JVM path is c:\Program Files\Java\jre7\bin\client\jvm.dll
JRE path is c:\Program Files\Java\jre7
CRT path is c:\Program Files\Java\jre7\bin\msvcr100.dll
5365 micro seconds to LoadJavaVM
Expanded wildcards:
    before: "lib/*;"
    after : "lib/a.jar;lib/b.jar;"
JavaVM args:
    version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 5
    option[ 0] = '-Dsun.java.launcher.diag=true'
    option[ 1] = '-Djava.class.path=.'
    option[ 2] = '-Djava.class.path=lib/a.jar;lib/b.jar;'
    option[ 3] = '-Dsun.java.command=test.B'
    option[ 4] = '-Dsun.java.launcher=SUN_STANDARD'
51245 micro seconds to InitializeJVM
Main class is 'test.B'
App's argc is 0
13358 micro seconds to load main class
----_JAVA_LAUNCHER_DEBUG----



REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
File test/A.java:
---
package test;

class A {
}
---

File test/B.java:
---
package test;

class B {
    public static void main(String[] args) {
        System.out.println("main() in class B executed");
    }
}
---

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Command line for executing the code must be modified e.g. like following:

java -cp "lib/*;" test.B

Please note that instead of "*" is there "*;". Then execution works as expected.

                                    

Comments
EVALUATION

http://hg.openjdk.java.net/hsx/hotspot-comp/jdk/rev/2dd41a2dfe54
                                     
2012-08-14
EVALUATION

http://hg.openjdk.java.net/hsx/hotspot-main/jdk/rev/2dd41a2dfe54
                                     
2012-08-11
EVALUATION

See also MS's release notes:
http://msdn.microsoft.com/en-US/library/ms235497%28v=VS.80%29.aspx
                                     
2012-05-10
SUGGESTED FIX

Stop linking with setarg.obj, however this could cause other side-effects
with the launcher wildcard processing behavior.
                                     
2012-02-27
EVALUATION

This started to happen when the compilers were updated from VC2003 to VS2010.
The launcher links with VS2010's setargv.obj which exhibits a different
behavior, which is reported here and closed by MS.
http://connect.microsoft.com/VisualStudio/feedback/details/98756/vs2005-setargv-obj-wildcard-handling-broken

In the previous versions the wildcard parameter was passed intact to
the launcher which would invoke its own wildcard expansions, but now
the setargv.obj decides to expand the wildcard inhibiting the launcher's
logic.

The debug output in the case where it works and the wildcard compononent
is passed to the launcher directly,
<snip>
430624 micro seconds to LoadJavaVM
Expanded wildcards:
    before: "lib\*"
    after : "lib\a.jar;lib\b.jar"
<snip>
                                     
2012-02-27
PUBLIC COMMENTS

In the failing case it appears as if the wildcard expansion is happening in the "shell". Consequently:

java -cp lib/* test.B

becomes

java -cp lib/a.jar lib/b.jar test.B

which naturally fails. I'm not sure why anyone would even think that a wildcard on a classpath option should actually work as the multiple entries would not form a single path definition with the necessary path seperator etc.

In the working case the launcher sees a single arg of "lib/*;"
                                     
2012-02-21
PUBLIC COMMENTS

Put this program in a dir and compile it:
class Bug {
    static public void main(String args[]) {
        for (String ss: args) System.out.println("ss - " + ss);
    }
}
Then run it like this:
     java Bug "./*"

On windows, in a 'cmd' shell, the following is output:
 6u29:
      ss = ./*
 7:
      ss - ./Bug.class
      ss - ./Bug.java

This is a change in behavior from 6 to 7.

In a cygwin shell, this is output by both jdk 6 and 7:
      ss - ./Bug.class
      ss - ./Bug.java

On solaris, this is output by both jdk 6 and 7 in csh, sh, bash:
      ss = ./*

The above shows what gets passed to a program for "./*".  
The section  "Understanding class path wildcards" here:
     http://docs.oracle.com/javase/7/docs/technotes/tools/windows/classpath.html
shows what is supposed to happen if you do manage to get ./* into the classpath seen by the java launcher.
                                     
2012-02-21



Hardware and Software, Engineered to Work Together