文件路径分隔符Java 7选项导致ExceptionInInitializerError异常。

21

我们在一台64位Windows Server 2008机器上运行一个TeamCity (7.0.3)代理。最近,当我们将代理升级以使用Java 7 (1.7.0_10)时,构建开始失败,并显示以下堆栈跟踪:

Error occurred during initialization of VM
java.lang.ExceptionInInitializerError
    at java.lang.Runtime.loadLibrary0(Runtime.java:841)
    at java.lang.System.loadLibrary(System.java:1084)
    at java.lang.System.initializeSystemClass(System.java:1145)
Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: 0
    at java.lang.String.charAt(String.java:658)
    at java.io.Win32FileSystem.<init>(Win32FileSystem.java:40)
    at java.io.WinNTFileSystem.<init>(WinNTFileSystem.java:37)
    at java.io.FileSystem.getFileSystem(Native Method)
    at java.io.File.<clinit>(File.java:156)
    at java.lang.Runtime.loadLibrary0(Runtime.java:841)
    at java.lang.System.loadLibrary(System.java:1084)
    at java.lang.System.initializeSystemClass(System.java:1145)

问题似乎源于TeamCity在代理程序的可执行命令中使用的"-Dfile.separator=\" java选项。我能够通过编写一个简单的“Hello World”类并在Windows机器上编译它,然后使用file.separator选项运行程序(即java -Dfile.separator=\ HelloWorld)来重现该问题。

我没有找到任何类似的错误报告。有人见过这样的情况吗?file.separator的行为在Java 7中有改变吗?

此外,我意识到\实际上是Windows的默认file.separator,所以我不认为代理程序真的需要在可执行命令中使用它,但我无法在TeamCity中找到一种方法告诉代理程序不要包含它。有可能做到这一点吗?


抛出ExceptionInInitializerError来指示在静态初始化程序或静态变量的初始化程序评估期间发生异常(参见[此处](http://www.cin.ufpe.br/~java/docs/langspechtml/javalang.doc.html))。也许您只是缺少静态块。 - Cesar Castro
谢谢,但这里不适用。失败的“Hello World”程序只包含一个带有System.out.println的主方法。 - GaZ
如果这是Java 7的新问题,那么可能是一个错误。是否使用\? - irreputable
1
\ 没有起作用。看起来是更新10出了问题,而更新9可以正常工作。唉。我将向Oracle创建一个错误报告。 - GaZ
TeamCity也受到了这个问题的影响。请参见TW-25070 - Eugene Petrenko
我可以确认,在更新到Java 7 Update 17(从7_11)之后,这仍然是一个问题。 - FazoM
2个回答

12
尝试使用JVM命令行参数-Dfile.separator=\/(即同时指定反斜杠和正斜杠) 。

1
这似乎解决了我们的问题。 谢谢! - Jay Askren

10

现在看起来java.exe会去掉结尾的\ (反斜杠)。

我有以下代码: import java.lang.*;

public class test {
  public static void main(String[] argz) { 
    for(String s : argz) {
     System.out.println("agg=" + s + "|");
    }

    System.out.println("prop=" +  System.getProperty("prop") + "|");
  }
}

我从 Java 1.7.0_07 和 _10 开始:

C:\Java\jdk1.7.0_07\bin\java.exe -cp . -Dprop=z\\ test a\\ b
agg=a\\|
agg=b|
prop=z\\|

和_10

C:\Java\jdk1.7.0_10\bin\java.exe -cp . -Dprop=z\\ test a\\ b
agg=a|
agg=b|
prop=z|

还有一个系列:

C:\Java\jdk1.7.0_07\bin\java.exe -cp . -Dprop=z\ test a\ b
agg=a\|
agg=b|
prop=z\|

和 _10

C:\Java\jdk1.7.0_10\bin\java.exe -cp . -Dprop=z\ test a\ b
agg=a|
agg=b|
prop=z|

3
看起来是JVM的一个bug,而且可能不只是TeamCity受到影响。之前,如果参数以\结尾,我们不需要使用引号,命令行解析器会正确处理。现在我们必须对这样的参数加引号。 - Pavel Sher
感谢您进行了这么详细的调查。我已经向Oracle反馈了1.7.0_10版本的错误,让我们拭目以待,看看会发生什么(如果有任何变化)。 - GaZ
GaZ,请您在这里分享问题链接。 - Eugene Petrenko
似乎这不是一个公开的漏洞跟踪器,但根据我收到的自动回复,该报告被分配了一个内部审查 ID 为 2406463。如果我从他们那里听到任何更多的消息,我会更新这个线程。 - GaZ
你把 bug 提交到哪里了?我本来期望在 http://bugs.sun.com/ 上看到它,但是那里没有。你用 http://bugreport.sun.com/bugreport/ 来提交的吗?恐怕它被提交到了一个无人关注的地方... - Pavel
哦,我刚刚填写了相同的内容,看到我重复了努力 - 直到审核后他们才会公开错误报告。所以他们在内部有另一个编号为#2426425的错误报告 :) 我不明白为什么他们不想公开等待审核的报告。此外,我希望根据我们看到的数字,每周不会有2万个新的错误报告 :) - Pavel

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