Question

I have written unit tests for a Swing GUI that creates JFileChooser. Since the unit tests are run on a build server as a service, the unit tests need to run as the local system account. However, when the unit tests try to create a new JFileChooser, they throw a NullPointerException.

I've reduced the problem to that of running the following main class as local system account (NOT THE REAL CODE)

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");
            }
        });
    }
}

Using the following build file.

<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>

If I run the code as my own user account, the JFileChooser appears (that's all I want it to do as the above stripped down code obviously doesn't do anything after that).

If I run the above code as the system account (e.g. by installing PsTools/PsExec and running PsExec.exe -s -i cmd.exe to start cmd as system account and then running the jar, then I get the following stack trace:

 [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)

How can I create a JFileChooser object within a JVM that has been launched by the local system account?

I'm currently using JVM version 1.7.0_25 32bit and have tested on both Windows Server 2008 and Windows 7. There's another requirement that means I can't switch from a 32bit JVM to 64bit JVM.

I've tried various suggestions from Google including.

  • Passing -Dswing.disableFileChooserSpeedFix=true
  • Passing -Duser.home=./
  • Passing -Dtemp.dir=C:/temp

... but none changed the result.

Thanks for any help.

Was it helpful?

Solution

This is not a JVM issue but a permissions issue. I recently encountered a similar stack trace running Java 8v92 on a Windows 10 machine.

To fix this, set the Windows Service to log on as an Administrator account (launch Services, highlight the service and show Properties, select Log On tab in Windows 10):

Set Windows Service to use an Admin account

OTHER TIPS

I believe is a Java 7 problem. Check your version and try with another. Or upgrade your java version.

I happened to have a very similar problem and I managed to solve it configuring the service to be executed with an admin account (in the config, not just starting it being an admin). Be aware that you will not be able to do this with an admin account that has no password (well, not without touching the registry).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top