在Windows(7?)上,Java7命令行的通配符扩展出现了问题。

16
我观察到在Windows上,Java7的通配符展开行为有些奇怪。
几个世纪以来,"*"和*之间有一个明显的区别。 然而,在Java7上(至少在Windows7上),这个区别似乎不再存在。
当我使用通配符类路径时,我注意到了这个问题。 尽管对通配符类路径进行了引用,但它仍然被展开。 因此,似乎不再可能将通配符传递给Java应用程序。
所以使用java -cp "somewhere/*"会失败("somewhere\*"也是如此)。
一个解决方法似乎是:java -cp "somewhere/*;",这样可以阻止展开。
为了验证这个行为,我编写了一个小的Echo.java类。
我发现,在Java 1.6.0中,引用的"*"和普通的*都能按预期工作, 而在Java7中,我总是得到展开的通配符。 到目前为止,这只在Windows7上观察到,不知道在XP上会发生什么。
问题出现在Windows上,因为黑暗时代的CMD.EXE从不扩展通配符(就像UNIX上的任何shell一样)。相反,每个可执行文件都必须使用setargv.obj来显式执行此操作。
我找到了两个相关的问题,似乎描述了类似的问题: 有其他人也观察到这个问题吗? 还是有一些不为人知的Windows或批处理文件设置可以控制这个问题吗?
Dieter.

1
如果您设置环境变量_JAVA_LAUNCHER_DEBUG,启动器将显示有关扩展类路径的其他信息。也许它会帮助您了解java.exe内部发生了什么。 - lxbndr
这个与编程有关的内容是:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7020954 - Oleg Mikheev
使用 _JAVA_LAUNCHER_DEBUG 也显示 "*" 衰减: java -cp . Echo "*" 命令行参数: argv[0] = C:\Program Files\Java\jdk1.7\bin\java.exe argv[1] = -cp argv[2] = . argv[3] = Echo argv[4] = Echo.class argv[5] = Echo.java - Ditz
谢谢,@Ditz - 这真的帮了我大忙!我正在使用Maven的exec插件,需要将通配符类路径传递给JVM(不使用shell globbing)。path/to/jars/*;解决了问题! - RubyTuesdayDONO
但是有一个警告 - 如果路径中的任何文件名包含分号(不太可能,但有可能),这可能会导致错误。 - RubyTuesdayDONO
在通配符后面加上分号对我没有起作用,所以最终我列出了所有的 jar 文件,这样就可以工作了。可恶的 Java7! - Guillaume
3个回答

7

是的,我注意到了同样的问题。

  • Java7更新4的发布说明中将其解释为“已知问题”。

  • 这是错误报告。修复程序将在Java7更新8中提供(当前版本为更新6)。

  • 请注意,没有shell选项可行的解决方法,因为在Windows中,shell不处理通配符扩展。(而在Unix中,shell执行扩展)。


0

对于这个被注释符 /* 破坏的问题,我没有直接的解决方案,但希望你可以使用以下脚本来缓解你的情况。

 libDir2Scan4jars="../test";cp=""; for j in `ls ${libDir2Scan4jars}/*.jar`; do if [ "$j" != "" ]; then cp=$cp:$j; fi; done; echo $cp| cut -c2-${#cp} > .tmpCP.tmp; export tmpCLASSPATH=`cat .tmpCP.tmp`; if [ "$tmpCLASSPATH" != "" ]; then echo .; echo "classpath set, you can now use  ~>         java -cp \$tmpCLASSPATH"; echo .; else echo .; echo "Error please check libDir2Scan4jars path"; echo .; fi; 

该脚本适用于Linux,也可以为Windows编写类似的脚本。如果将正确的目录作为“libDir2Scan4jars”的输入提供,则脚本将扫描所有JAR文件并创建一个类路径字符串,并将其导出到环境变量“tmpCLASSPATH”中。


0
我找到了一个通用的解决方案来解决Windows-Java-launcher-argument-wildcard-expansion问题:
从@argfile中获取的参数不会进行通配符扩展。例如:
java foo.Echo '*.txt'     => 1.txt 2.txt

echo "foo.Echo *.txt" >argfile
java @argfile             => *.txt

如果您有一个包装的BASH脚本,您可以执行以下操作:

argfile=c:/tmp/argfile$$;
echo foo.Echo "$@" >$argfile;
java @$argfile;

而且您的命令行参数不会被启动器通配符扩展。

已测试使用:

adopt_openjdk_15+36_swm_cert_v3
adopt_openjdk-11.0.11.9-hotspot
adopt_openjdk-14.0.2_12-hotspot
adopt_openjdk-16.0.1.9-hotspot
jdk-13.0.2+8
jdk-17.0.1+12

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接