JDK-8131329 : JVM silently expands command line arguments before invoking "main()"
  • Type: Bug
  • Component: tools
  • Sub-Component: launcher
  • Affected Version: 8u5
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_8
  • CPU: x86
  • Submitted: 2015-07-14
  • Updated: 2016-05-10
  • Resolved: 2015-07-15
Related Reports
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)

AFAIK any Java version from 1.0 up to and including 1.8

FULL OS VERSION :
Windows 8.1 Professional, AFAIK all other versions of MS Windows.
Does NOT occur on Linux JVMs!

A DESCRIPTION OF THE PROBLEM :
The line arguments of the JVM are suspect to an undocumented expansion:
Any argument that matches one or more files is replaced with the names of the files.

Notice that this is NOT the expansion that many shells do BEFORE executing "java.exe"; instead, the "java.exe" ITSELF does it before invoking "main()"!

This behavior is problematic when you want to pass a LITERAL "*", "?" or "[" to a Java program on the command line, e.g.:

      $ java.exe Calc 7 "*" 13
      $ java.exe Find . -name "*.java"

So far, I could not find a workaround.

The behavior is very confusing to the user, and forces programmers to change their command line syntax only to make it possible to run their programs on a WINDOWS JVM. Thus I consider this behavior as a bug

THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: Yes

THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Yes

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the test program with
java.exe -cp target/classes foo.Main a "*" b

Verify that the command line arguments of the running JVM with SYSINTERNALS PROCEXP:
"C:\Program Files\Java\jdk1.8.0_05\jre\bin\java.exe" -cp target/classes foo.Main a * b


EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected output:
args[0]= "a"
args[1]= "*"
args[2]= "b"
Done

Actual output:
args[0]= "a"
args[1]= ".classpath"
args[2]= ".project"
args[3]= ".settings"
args[4]= "pom.xml"
args[5]= "src"
args[6]= "target"
args[7]= "b"
Done
REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package foo;

public class Main {

	public static void main(String[] args) throws InterruptedException {
		for (int i = 0; i < args.length; i++) {
			System.out.println("args[" + i + "]= \"" + args[i] + "\"");
		}
		Thread.sleep(5000);
		System.out.println("Done");
	}
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Unfortunately I could not find a workaround.


Comments
Using cygwin: % cat Foo.java public class Foo { public static void main(String... args) { for (String s : args) { System.out.println("arg: " + s); } } } % $NSDK/bin/java Foo "*" arg: Foo.class arg: Foo.java arg: jdk9 Though the wildcard char * is quoted in the shell, the launcher "will" expand it. $NSDK/bin/java Foo "'*'" arg: '*' In conclusion java.exe on windows works differently than UNIX and will expand wildcards before invoking main, and the parsing follows the Microsoft standards as described here: https://msdn.microsoft.com/en-us/library/17w5ykft.aspx The application must take care of extra escapes required to tunnel a wildcard character through the shell and the java launcher's parsing layers.
17-07-2015

Email from Anthony VE > I'm writing you concerning bugs JDK-8131329 & JDK-8131680: JVM silently > expands command line arguments before invoking "main()" > > While the issue is not reproducible with cmd, it actually is with both > PowerShell and Cygwin. So most likely the reporter is using one of the > latter shells. > > Will you please add a comment to these bugs to explain that this is due > to the behavior of PowerShell/Cygwin? I believe it would be appreciated > by the reporter to know that you've been able to reproduce the issue & > help him/her to better understand why it isn't a bug in Java.
17-07-2015

I could not reproduce the issue. Closing this as Not an Issue.
15-07-2015

This is not a bug, this is a feature, yes in Windows it is the applications responsibility to expand wildcards, on *nix it is the shell. For your reading pleasure I have quoted an excerpt from an interview with Brian Kernighan at Princeton, who laments about this very behavior, read on.... "An analogous one which is probably more modern: If you look at DOS, MS-DOS, the notion of wildcard characters for filename expansion, is part of DOS, but in a very strange way. It's really not done by the command interpreter, COMMAND.COM or whatever, the way it would be in Unix, by a shell. But, rather, it's a service provided by individual programs, and that means that its properties-some programs don't have it, its properties might be somewhat different from one program to another, whereas in Unix it's known that it's done by a single program, in a single place, and therefore its properties are somewhat more uniform. That notion that there's the right place to do things is something that you maybe take for granted in Unix; it doesn't quite come up the same in other systems. And so explaining that to people, maybe is difficult."
15-07-2015

Moved to tools->launcher as the launcher handles argument processing on Windows
15-07-2015