NPE в Win32ShellFolder2.access при создании нового JFileChooser в качестве учетной записи локальной системы в Windows 7

Я написал модульные тесты для Swing GUI, который создает JFileChooser. Поскольку модульные тесты запускаются на сервере сборки как служба, модульные тесты должны запускаться как локальная системная учетная запись. Однако, когда модульные тесты пытаются создать новый 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)

Как я могу создать объект JFileChooser в JVM, который был запущен локальной системной учетной записью?

В настоящее время я использую 32-битную версию JVM 1.7.0_25 и проверил как на Windows Server 2008, так и на Windows 7. Есть еще одно требование, которое означает, что я не могу перейти с 32-битной JVM на 64-битную JVM.

Я пробовал различные предложения от Google, в том числе.

  • Передача -Dswing.disableFileChooserSpeedFix=true
  • Передача -Duser.home=./
  • Передача -Dtemp.dir = C: / temp

... но никто не изменил результат.

Спасибо за любую помощь.

3 ответа

Решение

Это не проблема JVM, а проблема с разрешениями. Недавно я столкнулся с подобной трассировкой стека под управлением Java 8v92 на компьютере с Windows 10.

Чтобы это исправить, настройте службу Windows для входа в систему с учетной записью администратора (запустите службы, выделите службу и выберите "Свойства", выберите вкладку "Вход в систему" ​​в Windows 10):

Настройка службы Windows для использования учетной записи администратора

Я считаю, что это проблема Java 7. Проверьте свою версию и попробуйте с другой. Или обновите версию Java.

У меня случилась очень похожая проблема, и мне удалось решить ее, настроив службу, выполняемую с учетной записью администратора (в конфигурации, а не просто при запуске в качестве администратора). Имейте в виду, что вы не сможете сделать это с учетной записью администратора, которая не имеет пароля (ну, не без касания реестра).

Другие вопросы по тегам