On a MacBook Pro (2015) with fresh-installed Big Sur and AdoptOpenJDK 11 I developed a Java program for educational purpose that uses the JFileChooser. I did not use any IDE-specific code. As the rest of the program does not matter, here is a minimum-example that produces the same problem for me (Note: Here only as an example, clicking the button will open the File Chooser, choosing a file and clicking OK will change the button's text to '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();
}
}
If I start the program via Terminal (java Test
or compiled as a jar with java -jar Test.jar
) everything works fine. I can open the File Chooser and it shows up my files and folders on my disk.
If I start the compiled jar via double-click, the program launches as well, but if I open the File Chooser I cannot see any files on my disk and hence I cannot load and save data to disk.
As I only have these problems on my Mac (not on Windows 10 or Lubuntu Linux) this might be a very specific problem due to false Java settings on my Mac. However, as I installed a fresh copy of Big Sur and AdoptOpenJDK 11 for Mac without changing anything, I wonder if this problem may occur for other people who want to run my program (teachers and students).
So what might be the problem and how to solve this (for me and potentially others)?
I already figured out with the activity monitor that the double-clicked jar is loaded with the JavaLauncher (but I cannot find it on disk and I cannot change any system settings for that).
I also searched for similar problems here. But these were mostly associated with saving files on wrong paths.
Would be nice to find a solution. Thank you for answering!
The mac has had a borderline silly (in that a ton of reviewers have derided this 'feature' as inane) security policy since Catalina (one version prior to Big Sur), where every app gets a popup-prompt the moment it tries to touch the disk, asking for permission from the user. Each major folder (Desktop, Documents, etc, eventually, whole disk) gets its own popup.
When you double click a jar file, the jar file runs 'as its own app' and gets its own popups. Presumably you denied it once, or possibly something is a little broken and those popups aren't showing.
In contrast, when running java
in the terminal, the java process so spawned ends up piggybacking off of the permissions of the Terminal application (if you don't want that, run open foo.jar
, which asks OS X to run the jar, and not java -jar foo.jar
). The moment you so much as start Terminal you already get a popup for full disk access, you presumably said 'yes' to that, and thus, any javas spawned by the shell spawned by the Terminal work fine.
There is an easy fix and a hard fix. The hard fix is to fully 'mac-osx-ize' your application. To do this, you will need to use jlink
and jpackage
which are part of your OpenJDK distribution. They're right next to the javac
and java
executables. You'll need to modularize to properly use these tools.
The reason it's a harder fix is because the official distribution model of java desktop apps has changed. In the past (up to java 8), the idea was: The end user makes an arrangement with Oracle: They download a java runtime (a 'JRE') from oracle. Oracle will maintain it (will run updaters and otherwise take responsibility if that JRE has a security leak and they don't tell you about it), and this JRE will then be used to run java apps. You (the developer of a desktop java app) distribute jar files.
This is no longer how it works.
That's why there is no JRE9 (azul and a few other parties still make them; this is an attempt to maintain an obsolete distribution model for those who aren't ready to upgrade their distribution strategies. Oracle does not ship JREs anymore, not since java9, intentionally). The new model matches what almost all serious java desktop apps were already doing anyway: You (the maker of the app) distribute a JVM that can run your app, not oracle. This way, you don't have to explain to your users where to download a JRE (your installer will do this), and you know exactly what version of JRE you are shipping to them, instead of praying that whatever they have can run your stuff.
This is what jlink
and jpackage
are all about. This way you end up with an .app
file, and this then fits normal mac apps: If a user denies disk access, and they change their mind later, they can just drag the .app into the appropriate list in the security widget of their System Preferences window like any other mac app. (And, yeah, most users don't know how to do that. Apple messed this part up, nothing java can do to fix this oversight in userfriendliness of OS X).
The easy way? Eh, commit to your current distribution model. Might as well tell them about how to start Terminal and run java
from there - you're already asking them to install from AdoptOpenJDK and more or less forcing them to take care of keeping it up to date: You're already treating your end user as an advanced user who knows how to manage their own system and install complicated software. Might as well go the extra mile and tell them about Terminal.app.