我为创建 JFileChooser 的 Swing GUI 编写了单元测试。由于单元测试作为服务在构建服务器上运行,因此单元测试需要作为本地系统帐户运行。但是,当单元测试尝试创建新的 JFileChooser 时,它们会抛出 NullPointerException。
我已将问题减少为将以下主类作为本地系统帐户运行的问题(不是真实代码)
package com.example.mcgr;
import javax.swing.*;
import java.io.IOException;
public class FileChooserAsSystem {
public static void main(String[] args) throws IOException {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFileChooser fileChooser = new JFileChooser();
fileChooser.showDialog(null, "Ok");
}
});
}
}
使用以下构建文件。
<project>
<target name="clean">
<delete dir="build"/>
</target>
<target name="compile" depends="clean">
<mkdir dir="build/classes"/>
<javac srcdir="src" destdir="build/classes"/>
</target>
<target name="jar" depends="compile">
<mkdir dir="build/jar"/>
<jar destfile="build/jar/FileChooserAsSystem.jar" basedir="build/classes">
<manifest>
<attribute name="Main-Class" value="com.example.mcgr.FileChooserAsSystem"/>
</manifest>
</jar>
</target>
<target name="run">
<java jar="build/jar/FileChooserAsSystem.jar" fork="true"/>
</target>
</project>
如果我以我自己的用户帐户运行代码,则会出现 JFileChooser(这就是我想要它做的所有事情,因为上面的精简代码显然在那之后不会做任何事情)。
如果我将上述代码作为系统帐户运行(例如,通过安装 PsTools/PsExec 并运行
PsExec.exe -s -i cmd.exe
以将 cmd 作为系统帐户启动,然后运行 jar,那么我会得到以下堆栈跟踪:
[java] Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
[java] at sun.awt.shell.Win32ShellFolder2.access$200(Win32ShellFolder2.java:72)
[java] at sun.awt.shell.Win32ShellFolder2$1.call(Win32ShellFolder2.java:242)
[java] at sun.awt.shell.Win32ShellFolder2$1.call(Win32ShellFolder2.java:237)
[java] at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
[java] at java.util.concurrent.FutureTask.run(FutureTask.java:166)
[java] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
[java] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
[java] at sun.awt.shell.Win32ShellFolderManager2$ComInvoker$3.run(Win32ShellFolderManager2.java:502)
[java] at java.lang.Thread.run(Thread.java:724)
如何在本地系统帐户启动的 JVM 中创建 JFileChooser 对象?
我目前正在使用 JVM 版本 1.7.0_25 32 位,并已在 Windows Server 2008 和 Windows 7 上进行了测试。还有另一个要求意味着我无法从 32 位 JVM 切换到 64 位 JVM。
我尝试了谷歌的各种建议,包括。
- 传递 -Dswing.disableFileChooserSpeedFix=true
- 传递 -Duser.home=./
- 传递 -Dtemp.dir=C:/temp
...但没有人改变结果。
谢谢你的帮助。