java—为什么jar文件在通过双击启动时没有从磁盘读取的权限—但从终端启动时没有权限?

brjng4g3  于 2021-06-29  发布在  Java
关注(0)|答案(2)|浏览(360)

在MacBookPro(2015)上,新安装了big-sur并采用了OpenJDK 11,我开发了一个用于教育目的的java程序,该程序使用jfilechooser。我没有使用任何特定于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 或者编译成一个带有 java -jar Test.jar )一切正常。我可以打开文件选择器,它会在我的磁盘上显示我的文件和文件夹。
如果我通过双击启动编译的jar,程序也会启动,但是如果我打开文件选择器,我在磁盘上看不到任何文件,因此我无法将数据加载并保存到磁盘。
由于我的mac上只有这些问题(不是Windows10或LubuntuLinux),这可能是一个非常特殊的问题,因为mac上的java设置错误。然而,当我安装了一个新的big-sur版本,并采用openjdk 11 for mac而没有做任何更改时,我想知道这个问题是否会发生在其他想要运行我的程序的人(老师和学生)身上。
那么问题是什么?如何解决这个问题(对我和其他潜在的人来说)?
我已经在activitymonitor中发现双击jar是用javalauncher加载的(但是我在磁盘上找不到它,也不能为此更改任何系统设置)。
我也在这里搜索类似的问题。但这些主要与在错误路径上保存文件有关。
很高兴能找到解决办法。谢谢你的回答!

c3frrgcw

c3frrgcw1#

我猜是这样的:
您在文件选择器中查看的文件夹/文件具有用户a的读取权限,但不允许用户b的读取权限
当您通过终端运行时,应用程序是以用户身份运行的
当您通过双击运行时,应用程序将作为用户b运行

kcwpcxri

kcwpcxri2#

自从catalina(big-sur之前的一个版本)以来,mac一直有一个近乎愚蠢的安全策略(很多评论者都嘲笑这个“特性”是空洞的),每个应用程序在试图接触磁盘时都会得到一个弹出提示,请求用户的许可。每个主要文件夹(桌面、文档等,最终是整个磁盘)都有自己的弹出窗口。
当您双击一个jar文件时,jar文件将“作为自己的应用程序”运行,并获得自己的弹出窗口。大概你否认过一次,或者可能是有点坏了,那些弹出窗口没有显示出来。
相反,跑步时 java 在终端中,这样生成的java进程最终会占用终端应用程序的权限(如果不需要,请运行 open foo.jar ,它要求osx运行jar,而不是 java -jar foo.jar ). 当你启动终端的时候,你已经得到了一个完整磁盘访问的弹出窗口,你可能会说'是',因此,任何由终端产生的shell产生的javas都可以正常工作。
有一个简单的解决办法,也有一个困难的解决办法。解决方法是完全“macosx化”你的应用程序。为此,您需要使用 jlink 以及 jpackage 它们是openjdk发行版的一部分。他们就在公园旁边 javac 以及 java 可执行文件。您需要模块化来正确使用这些工具。
它之所以更难修复,是因为java桌面应用程序的官方发行模式已经改变。在过去(直到Java8),想法是:最终用户与oracle达成协议:他们从oracle下载java运行时(一个“jre”)。oracle将维护它(如果jre有安全漏洞,并且他们没有告诉你),那么它将运行更新程序并承担责任,然后这个jre将被用来运行java应用程序。您(桌面java应用程序的开发人员)分发jar文件。
现在已经不是这样了。
这就是为什么没有jre9(azul和其他一些政党仍然制作它们;这是为那些还没有准备好升级分销策略的人维护过时的分销模式的一种尝试。oracle不再提供jre了,自从java9之后就没有了。新的模式符合几乎所有严肃的java桌面应用程序已经在做的事情:你(应用程序的制造商)分发一个可以运行你的应用程序的jvm,而不是oracle。这样,你就不必向你的用户解释在哪里下载jre(你的安装程序会这样做),你也可以确切地知道你要向他们提供什么版本的jre,而不是祈祷他们拥有的任何东西都可以运行你的东西。
这是什么 jlink 以及 jpackage 都是关于你的。这样你就得到了一个 .app 文件,然后这就适合了普通的mac应用程序:如果用户拒绝磁盘访问,并且他们后来改变了主意,他们可以像其他任何mac应用程序一样,将.app拖到系统首选项窗口的安全小部件中的相应列表中(而且,是的,大多数用户都不知道该怎么做。苹果把这一部分搞砸了,java无法弥补OSX在用户友好性方面的缺陷。
简单的方法?呃,坚持你现在的分销模式。不妨告诉他们如何启动终端并运行 java 从这里开始——你已经要求他们从OpenJDK安装,或多或少地迫使他们注意保持最新:你已经把你的最终用户当作一个高级用户,知道如何管理自己的系统和安装复杂的软件。不如多走一步,告诉他们terminal.app的事。

相关问题