JDK-7146424 : Wildcard expansion for single entry classpath
  • Type: Bug
  • Component: tools
  • Sub-Component: launcher
  • Affected Version: 7,7u6
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS:
    windows,windows_xp,windows_2008,windows_7 windows,windows_xp,windows_2008,windows_7
  • CPU: generic,x86
  • Submitted: 2012-02-16
  • Updated: 2017-05-17
  • Resolved: 2012-08-10
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 JDK 8
7u10Fixed 8 b52Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
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
verified in jdk8 b92
06-06-2013

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

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

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

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>
27-02-2012

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

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.
21-02-2012

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/*;"
21-02-2012