4

在全新安装 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();
  }
}

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

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

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

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

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

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

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

4

2 回答 2

6

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

经过几个小时的折腾,我想出了如何根据上面的一些方法来修复它(谢谢!)......原来的海报太接近了!

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

通过进入 System Preferences -> Security -> Privacy -> Full Disk Access,我能够导航到上面的 Jar Launcher.app 并将其添加到列表中,然后可以双击我的 jar 文件并像往常一样使用完整的访问文件系统:)

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

于 2021-03-23T11:27:12.220 回答
3

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

当您双击一个 jar 文件时,该 jar 文件“作为它自己的应用程序”运行并获得它自己的弹出窗口。大概你否认过一次,或者可能有些东西有点坏了,那些弹出窗口没有显示。

相反,当java在终端中运行时,生成的 java 进程最终会捎带终端应用程序的权限(如果您不希望这样做,请运行open foo.jar,它要求 OS X 运行 jar,而不是java -jar foo.jar)。在您启动终端的那一刻,您已经获得了一个完整磁盘访问的弹出窗口,您可能对此说“是”,因此,终端产生的外壳产生的任何 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 , 故意地)。新模型与几乎所有严肃的 Java 桌面应用程序已经在做的事情相匹配:(应用程序的制造商)分发可以运行您的应用程序的 JVM,而不是 oracle。这样,您不必向您的用户解释在哪里下载 JRE(您的安装程序会这样做),并且您确切知道要向他们发送的 JRE 版本,而不是祈祷他们拥有的任何东西都可以运行您的东西。

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

简单的方法?嗯,致力于您当前的分销模式。不妨告诉他们如何启动终端并java从那里运行 - 您已经要求他们从 AdoptOpenJDK 安装,并且或多或少地迫使他们注意保持最新:您已经将您的最终用户视为知道如何管理自己的系统和安装复杂软件的高级用户。不妨加倍努力,告诉他们有关 Terminal.app 的信息。

于 2020-12-27T19:40:41.523 回答