在 Windows 7 中创建新的 JFileChooser 作为本地系统帐户时 Win32ShellFolder2.access 中的 NPE

use*_*450 5 java swing unit-testing jfilechooser local-system-account

我已经为创建 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");
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

使用以下构建文件。

<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>
Run Code Online (Sandbox Code Playgroud)

如果我以我自己的用户帐户运行代码,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)
Run Code Online (Sandbox Code Playgroud)

如何在本地系统帐户启动的 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

......但没有改变结果。

谢谢你的帮助。

sjg*_*jgp 3

这不是 JVM 问题,而是权限问题。我最近在 Windows 10 计算机上运行 Java 8v92 时遇到了类似的堆栈跟踪。

要解决此问题,请将 Windows 服务设置为以管理员帐户身份登录(启动服务,突出显示该服务并显示属性,在 Windows 10 中选择“登录”选项卡):

将 Windows 服务设置为使用管理员帐户