为什么通过双击启动时 jar 文件没有从磁盘读取的权限 - 但如果从终端启动则没有权限?

use*_*726 13 java macos terminal jar adoptopenjdk

在全新安装 Big Sur 和 AdoptOpenJDK 11 的 MacBook Pro (2015) 上,我开发了一个使用 JFileChooser 的用于教育目的的 Java 程序。我没有使用任何 IDE 特定的代码。由于程序的其余部分并不重要,这里是一个对我产生相同问题的最小示例(注意:这里仅作为示例,单击按钮将打开文件选择器,选择一个文件并单击“确定”将更改按钮的文本为“确定”):

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

如果我通过终端启动程序(java Test或编译为 jar java -jar Test.jar),一切正常。我可以打开文件选择器,它会显示磁盘上的文件和文件夹。

如果我通过双击启动编译的jar ,该程序也会启动,但如果我打开文件选择器,我看不到磁盘上的任何文件,因此无法将数据加载和保存到磁盘。

由于我只在 Mac 上遇到这些问题(在 Windows 10 或 Lubuntu Linux 上没有),这可能是一个非常具体的问题,因为我的 Mac 上的 Java 设置错误。但是,由于我安装了 Big Sur 的全新副本和 AdoptOpenJDK 11 for Mac 且未进行任何更改,我想知道其他想要运行我的程序的人(教师和学生)是否会出现此问题。

那么问题可能是什么以及如何解决这个问题(对于我和可能的其他人)?

我已经通过活动监视器发现双击的 jar 已通过 JavaLauncher 加载(但我在磁盘上找不到它,并且无法更改任何系统设置)。

我也在这里搜索过类似的问题。但这些大多与将文件保存在错误的路径有关。

找到解决方案会很高兴。谢谢您的回答!

小智 19

我遇到了同样的问题 - 几年前我编写了一个 java-for-all-desktops jar 应用程序,它在所有 java 版本、所有 Mac OS 和 Windows 上都运行良好,直到我将 jar 文件放在 Big Sur (OSX 11.2) 上,此时它无法从常规文件系统读取或写入常规文件系统。就其本身而言,它默认只读取和写入 /private/var... 中的 tmp 区域,而不是读取和写入包含 jar 文件的目录,并可以选择使用 jFileChooser 在真实文件系统中移动。如果我明确地将其设置为桌面上的开头,那么它可以移动到不同的目录,但看不到或访问文件。

经过几个小时的努力后,我根据上面的一些内容找到了如何修复它(谢谢!)...原始海报非常接近!

我发现在 /System/Library/CoreServices/Jar Launcher.app 中双击 JAR 文件时启动 JAR 文件的程序

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

不需要它来解决我的问题,因为,正如你们上面所说的那样,java似乎从终端或Jar Launcher继承了它的访问权限,但如果有人需要,您也可以添加java本身及其任何模块到完整磁盘访问列表(如上所述)。最简单的方法是使用 java -jar YourProgram.jar 从终端启动 jar,然后,当 jar 出现在扩展坞中时,右键单击它并单击在 Finder 中打开。这将打开包含 java 可执行文件的文件夹。然后您可以用鼠标选择它们并将它们直接拖到“完整磁盘访问”列表中。我一路上尝试过,但是通过双击罐子来使罐子正常工作既不够也没有必要。享受!


rzw*_*oot 5

自 Catalina(Big Sur 之前的一个版本)以来,Mac 一直有一个近乎愚蠢的安全策略(因为大量评论家嘲笑这个“功能”是愚蠢的),每个应用程序在尝试触摸时都会弹出提示磁盘,请求用户许可。每个主要文件夹(桌面、文档等,最终是整个磁盘)都有自己的弹出窗口。

当您双击 jar 文件时,该 jar 文件会“作为自己的应用程序”运行并获得自己的弹出窗口。大概您曾经拒绝过它,或者可能有些东西有点损坏并且那些弹出窗口没有显示。

相反,当java在终端中运行时,如此生成的 java 进程最终会捎带终端应用程序的权限(如果您不希望这样,请运行 run open foo.jar,它会要求 OS X 运行 jar,而不是运行java -jar foo.jar)。当您启动终端时,您已经看到一个用于完全磁盘访问的弹出窗口,您可能对此表示“是”,因此,由终端生成的 shell 生成的任何 java 都可以正常工作。

有一个简单的修复和一个困难的修复。硬修复是完全“mac-osx-ize”您的应用程序。为此,您需要使用OpenJDK 发行版中的jlink和。jpackage它们就在javacjava可执行文件旁边。您需要模块化才能正确使用这些工具。

这是一个更难修复的原因是因为 java 桌面应用程序的官方分发模型已经改变。在过去(Java 8 之前),想法是:最终用户与 Oracle 做出安排:他们从 Oracle 下载 Java 运行时(“JRE”)。Oracle 将维护它(如果该 JRE 存在安全漏洞并且他们没有告诉您,将运行更新程序,否则将承担责任),然后该 JRE 将用于运行 java 应用程序。您(桌面 Java 应用程序的开发人员)分发 jar 文件。

现在已经不再是这样了

这就是为什么没有JRE9(azul 和其他一些团体仍在制造它们;这是为那些还没有准备好升级其分发策略的人维护过时的分发模型的尝试。Oracle 不再提供 JRE,从 java9 开始就不再提供 JRE) , 故意地)。新模型与几乎所有严肃的 Java 桌面应用程序已经在做的事情相匹配:(应用程序的制造商)分发可以运行您的应用程序的 JVM,而不是 Oracle。这样,您不必向用户解释在哪里下载 JRE(您的安装程序将执行此操作),并且您确切地知道要向他们提供的 JRE 版本,而不是祈祷他们拥有的任何东西都可以运行您的东西。

这就是jlink一切jpackage。这样你最终会得到一个.app文件,这适合普通的 Mac 应用程序:如果用户拒绝磁盘访问,并且后来改变了主意,他们只需将 .app 拖到系统偏好设置的安全小部件中的相应列表中即可窗口就像任何其他 Mac 应用程序一样。(是的,大多数用户不知道如何做到这一点。Apple 搞砸了这部分,java 无法修复 OS X 用户友好性方面的这一疏忽)。

最简单的方法?呃,坚持你当前的分销模式。不妨告诉他们如何启动终端并java从那里运行 - 您已经要求他们从 AdoptOpenJDK 安装,并或多或少地迫使他们保持最新状态:您已经将您的最终用户视为知道如何管理自己的系统和安装复杂软件的高级用户。不妨多做一点,告诉他们 Terminal.app。