为什么通过双击启动JAR文件时无法读取磁盘权限,但从终端启动则可以?

13
在一台安装了Big Sur和AdoptOpenJDK 11的MacBook Pro(2015)上,我开发了一个用于教育目的的Java程序,该程序使用JFileChooser。我没有使用任何特定于IDE的代码。由于程序的其余部分并不重要,这里给出了一个最小化的示例,它对我产生了相同的问题(注意:这只是一个示例,单击按钮将打开文件选择器,选择一个文件并单击“确定”将更改按钮的文本为“OK”)。
import javax.swing.*;
import java.awt.event.*;

public class Test extends JFrame implements ActionListener {

  private JFileChooser jf;
  private JButton jb;

  public Test() {
    setSize(480,320);    
    jf = new JFileChooser();
    jf.setDialogType(JFileChooser.OPEN_DIALOG);
    jb = new JButton("CLICK ME");
    jb.addActionListener(this);
    add(jb);
    setVisible(true);
  }

  public void actionPerformed(ActionEvent e) {
    if (e.getSource().equals(jb)) {
        jf.setVisible(true);
        final int result = jf.showOpenDialog(null);
        if (result == JFileChooser.APPROVE_OPTION) {
          jb.setText("OK");
        }
    }
  }

  public static void main(String[] args) {
      new Test();
  }
}

如果我通过终端启动程序(使用“java Test”或者编译成带有“java -jar Test.jar”命令的jar包),一切正常。我可以打开文件选择器并显示磁盘上的文件和文件夹。
如果我通过双击编译的jar包启动程序,程序也能启动,但是如果我打开文件选择器,我看不到磁盘上的任何文件,因此我无法读取和保存数据到磁盘中。
由于这些问题只在我的Mac上出现(而不是在Windows 10或Lubuntu Linux上),所以这可能是由于我Mac上错误的Java设置导致的非常特定的问题。然而,由于我安装了最新的Big Sur和适用于Mac的AdoptOpenJDK 11,且没有进行任何更改,我想知道是否其他人运行我的程序时也会遇到此问题(教师和学生)。
那么问题可能是什么,如何解决这个问题(对我和其他人)呢?
我已经通过活动监视器找到了通过双击加载的jar包是由JavaLauncher加载的(但我找不到它在哪里,并且我不能更改任何系统设置)。
我还在这里搜索类似的问题。但这些问题大多与将文件保存到错误路径有关。
希望能找到解决方案。感谢您的回答!
3个回答

18

我曾经遇到过同样的问题 - 几年前我写了一个适用于所有桌面的Java jar应用程序,在所有Java版本和Mac OS和Windows上都可以正常工作,直到我将jar文件放在Big Sur(OSX 11.2)上时,它就无法读取或写入常规文件系统。 它仅默认读写到/ private / var中的临时区域...而不是到包含jar文件的目录,并使用jFileChooser来移动真实文件系统,如果我将其明确设置为启动Desktop,则可以移动到不同的目录,但无法查看或访问文件。

经过多个小时的尝试,我基于上述内容找到了解决方法(感谢!)...原始发布者也非常接近解决!

我找到了在双击JAR文件时启动JAR文件的程序,它位于/System/Library/CoreServices/Jar Launcher.app中

通过进入系统偏好设置->安全性->隐私->完全磁盘访问权限,我能够导航到并将上述Jar Launcher.app添加到列表中,然后我的jar文件就可以像以前一样双击并具有对文件系统的完全访问权限:)

因为正如你们所说,java似乎从终端或Jar Launcher中继承其访问权限,所以并不需要解决我的问题。但是如果有人需要,也可以将Java本身及其任何模块添加到完全磁盘访问列表中(如上所述)。最简单的方法是使用java -jar YourProgram.jar从终端启动您的jar文件,然后,在dock中出现jar文件时,右键单击它并单击“在Finder中打开”。这将打开包含java可执行文件的文件夹。然后,您可以使用鼠标选择它们并将它们拖到完全磁盘访问列表中。我在路上试过了这种方法,但双击JAR文件并不足以使其正常工作,既不充分也不必要。祝玩得愉快!


1
经过几周的尝试解决这个问题,你在这里的答案终于帮助了我。现在我可以再次运行我的jar文件,谢谢! - dma
1
我一直在寻找名为“Jar Launcher.app”的文件,但是无法找到它,后来发现我有一个名为“JavaLauncher.app”的文件(在macOS 11.4 Big Sur上)...它起作用了...感谢你找到这个。 - Jagdish Adusumalli
1
我在寻找名为“Jar Launcher.app”的文件时无法找到它,后来发现我有一个名为“JavaLauncher.app”的文件(在macOS 11.4 Big Sur上)...它起作用了...感谢你找到这个。 - Jagdish Adusumalli
1
谢谢!我在Mac上没有看到我的外部SSD,即使Java有完全磁盘访问权限。然后我将JavaLauncher.app添加到列表中,现在它能够列出SSD内的文件夹和文件。 - Teddy
谢谢。我甚至认为需要使用终端来启动Jar文件。 - Hide in bubble

5
自Catalina(Big Sur之前的一个版本)以来,Mac的安全策略变得有点可笑(许多评论家已经将此“功能”批评为愚蠢),每个应用程序在尝试触及磁盘时都会弹出提示窗口,要求用户授权。每个主要文件夹(桌面、文档等,最终是整个磁盘)都有自己的弹出窗口。
双击jar文件时,jar文件作为其自己的应用程序运行,并获得自己的弹出窗口。可能你拒绝了它一次,或者可能有一些小问题导致这些弹出窗口没有显示。
相比之下,在终端中运行java时,由此产生的java进程会背靠终端应用程序的权限(如果您不想要这样,运行open foo.jar,请求OS X运行jar文件,而不是java -jar foo.jar)。只要您启动终端,您就会立即获得关于完整磁盘访问的弹出窗口,您可能已经回答过“是”,因此终端生成的任何javas都可以正常工作。
有一个简单的解决方法和一个困难的解决方法。困难的解决方法是完全“mac-osx-ize”您的应用程序。为此,您将需要使用jlinkjpackage,它们是OpenJDK分发的一部分。它们就在javacjava可执行文件旁边。您需要模块化才能正确使用这些工具。
之所以这是一个更难的解决方法,是因为Java桌面应用程序的官方分发模型已经改变了。过去(直到Java 8),想法是:最终用户与Oracle达成协议:他们从Oracle下载Java运行时(“JRE”)。 Oracle将对其进行维护(运行更新程序并负责处理该JRE是否存在安全漏洞,如果没有告诉您,则会采取措施),然后使用此JRE来运行Java应用程序。您(桌面Java应用程序的开发人员)分发jar文件。 现在不再这样了。
这就是为什么没有JRE9的原因(Azul和其他几个方面仍在制作它们;这是为那些尚未准备好升级其分发策略的人维护过时的分发模型的尝试。Oracle自Java9以来不再提供JRE,这是有意的)。新模型匹配几乎所有严肃的Java桌面应用程序已经在做的事情:(应用程序的制造者)分发可以运行您的应用程序的JVM,而不是Oracle。这样,您不必向用户解释从哪里下载JRE(安装程序将为此执行),并且您知道正在向他们发布哪个版本的JRE,而不是祈求他们的任何东西都能够运行您的应用程序。
这就是和的全部内容所在。这样你就会得到一个<.app>文件,然后它就适合普通的Mac应用程序:如果用户拒绝了磁盘访问权限,并且他们随后改变了想法,他们只需将<.app>拖到其系统偏好设置窗口中的安全小部件中的适当列表中,就像其他的Mac应用程序一样。(是的,大多数用户不知道如何操作。苹果在这方面搞砸了,Java无法解决OS X的这种用户友好性疏忽问题)
简单的方法?呃,坚持您当前的分发模型。最好告诉他们如何启动终端并从那里运行 - 您已经要求他们从AdoptOpenJDK安装并强制他们负责保持更新:您已经将最终用户视为知道如何管理自己的系统并安装复杂软件的高级用户。不妨再多走一步,告诉他们有关Terminal.app。

可能是这个问题: 可能出了什么问题,因为当我通过双击启动应用程序时没有安全弹窗。或者也许我曾经点击过“不允许”(记不清了,但可能是)。当然,我总体上同意使用Terminal。因此,“完全将应用程序'osx-ize'”的论点是有道理的 - 比“应用程序占用太多磁盘空间”的论点更好,因为这也可能发生在其他人身上。正如你提到的,有一些工具,如launch4j等,适用于其他系统等。 - user14896726
检查您的系统偏好设置安全选项卡。有一个选项可以选择“完全磁盘访问”和“文件和文件夹”。如果运气好,那个jar包就在里面,如果不在,您可以将其拖入其中一个并勾选复选框。 - rzwitserloot
这对于我 MacBook 上的 JAR 文件不起作用,只适用于应用程序。 - user14896726
然而,来自@rzwitserloot的原始答案,使用jlink和jpackage创建一个应用程序文件就解决了问题。这个方法完美地解决了问题。第一次打开新应用程序时,它会要求我授权访问。我同意了并且它工作正常。此外:这种方法对其他人也很容易。 - user14896726
同时,我总是使用jpackage创建部署包来与他人共享我的应用程序,例如exe或pkg。即使不使用jlink,它也可以正常工作,并且非常易于使用,只需一个终端命令行即可。这解决了所有问题。 - user14896726

0
使用Oracle的jpackage将我的jar文件打包成.dmg文件,效果很好。
一旦进入JFileChooser窗口,它会提示您在所选文件夹中访问权限。
请注意,这将显著增加应用程序的大小。
以下是我用来创建它的脚本:
VERSION=your_version_or_command_to_extract
echo "Creating DMG for version $VERSION"

JAR="your_jar_name_in_target-$VERSION.jar"

jpackage --input target/ \
  --name MyApp \
  --main-jar $JAR \
  --main-class org.myapp.Main \
  --type dmg \
  --app-version $VERSION \
  --vendor "Your name" \
  --copyright "Copyright 2023 Your name" \
  --mac-package-name "Your App Name" \
  --mac-package-identifier "org.myapp" \
  --verbose \
  --java-options '--enable-preview'

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