Bundling Java applications for Mac OS X Catalina

catalinajava

I write amateur Java scientific applications which I provide freely for a small audience. (Probably I am the main user.) Most of them are still compiled under Java 1.6 where they run fine on Mojave either as jar files or as applications with the standard package contents structure shown below.

Package contents of Java 1.6 app

Under Catalina the applications no longer launch and I get a screen telling me that I need to install the legacy Java SE 6 runtime, which, of course, is already installed.

Install legacy Java 1.6

However if I remove the jar file (here Motivator.jar) from the app package and double-click it on the desktop (right-clicking to by-pass Gatekeeper) it runs fine.

So in one sense I am OK. But this is a Mac and I would prefer my applications to look like Mac applications on the desktop and when they run (i.e. not have the name of the class with my main method show).

Anyone know if it is possible to package a jar file as a Mac application any more? I can recompile with a higher version of Java if I have to.

Best Answer

Disclaimer
This is a provisional answer to my own question, which I will not accept until I have finally tested it. However, as people are encountering various problems with Java apps on the Mac I thought it useful to post to help others and allow suggestions for improvements.

Reason for the Behaviour Explained
It turned out that:

  1. The reason that my application failed to run was because the Catalina update had removed the Java SE 6 Runtime from the JavaVirtualMachine directory where it resided on a machine running an earlier version of Mac OS X: /Library/Java/JavaVirtualMachines

  2. My application ran as a ‘naked’ jar file because there was a copy of Java 1.8 from Oracle in that directory which Jar Launcher (the app that handles jar files) must have employed.

  3. When I copied the 1.6.0.jdk directory from another machine into the JavaVirtualMachine directory (just dragged and dropped it all over — needed an admin password) it ran from the packaged app as shown below.

Packaged Java App running under Catalina and Java 1.6

General Point: Apple’s legacy Java SE 6 Runtime does run under Catalina
There is an article on Ars Technica that states:

And a few longstanding components of macOS haven’t made the jump to 64-bit. These include… the old Apple-maintained Java 6 Runtime…

This had suggested to me (as also the kind comment by @greg-449) that the Java SE 6 Runtime was 32-bit. However I found a thread on the MacRumors forum about the different problem of Catalina preventing installation of Java SE 6 Runtime for a commercial app that requires it. When that was eventually overcome, the app worked. This was what caused me to check things out, confirming that Apple’s legacy Java SE 6 does run under Catalina.

A solution for the developer — replacing the JavaApplicationStub?
To re-emphasize, I am concerned with delivering a Mac app that just works after the user has performed an easy Java install. I can’t expect him to fiddle around trying to install the legacy Java 6 runtime to get my app to work.

It would seem that it is the JavaApplicationStub (in the application bundle) that ‘informs’ the system where the Java runtime is to run the application. Originally this could be handled for the developer by a little Apple utility, jarbundler, which never worked with Oracle Java runtime. (Thanks @abc for reminding me of this.) However it turns out that there have been ways round this problem, as described on this Stack Overflow post, and there is a replacement for JavaApplicationStub: universalJavaApplicationStub — on GitHub.

This latter seems to be the way to go, and I will update this answer when I have tested it.