JDK-8166683 : On macOS (Mac OS X) getting a ScreenMenuBar when not running "com.apple.laf.AquaLookAndFeel"
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: os_x
  • CPU: x86
  • Submitted: 2016-09-14
  • Updated: 2020-09-08
  • Resolved: 2016-12-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9 b150Fixed
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
Java(TM) SE Runtime Environment (build 9-ea+135)

ADDITIONAL OS VERSION INFORMATION :
 Mac OS X, 10.11.6 build: 15G1004

A DESCRIPTION OF THE PROBLEM :
 On macOS (Mac OS X) getting a screen menu bar, when not running "com.apple.laf.AquaLookAndFeel" can only be achieved when setting the ComponentUI of a JMenuBar to an instance of com.apple.laf.AquaMenuBarUI.
Since JDK 9 this is only possible when using "--add-exports" as a workarround.
In contrary it is possible to instantiate javax.swing.plaf.synth.SynthMenuBarUI.
Why not com.apple.laf.AquaMenuBarUI?

The screen menu bar is a macOS desktop feature which is common to every macOS desktop application. 
    If a desktop application does not have such a screen menu bar it will not be accepted by the user on macOS.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Set another LAF than "AquaLookAndFeel", i.e. UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
Create a menubar in a JFrame that is a screen menu bar on macOS (-Dapple.laf.useScreenMenuBar=true)

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The menu bar should appear as ScreenMenuBar on top of the display.
ACTUAL -
IllegalAccessError is thrown

ERROR MESSAGES/STACK TRACES THAT OCCUR :
"Exception in thread "AWT-EventQueue-0" java.lang.IllegalAccessError: class ScreenMenuBarLAF$ScreenJMenuBar  (in unnamed module @0x3b9797b1) cannot access class com.apple.laf.AquaMenuBarUI (in module java.desktop) because module java.desktop does not export com.apple.laf to unnamed module @0x3b9797b1"

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;

public class ScreenMenuBarLAF
{
    public static class ScreenJMenuBar extends JMenuBar
    {
        ScreenJMenuBar()
        {
            super();
        }
        
        public void updateUI()
        {
            // use AquaMenuBarUI to get the JJMenuBar as ScreenMenuBar
            // and not inside the JFrame
            ComponentUI cui = new com.apple.laf.AquaMenuBarUI(); // <- IllegalAccessError 
            // ComponentUI cui = new javax.swing.plaf.synth.SynthMenuBarUI();
            setUI(cui);
        }
    }

    private static void createAndShowGUI() 
    {
        System.err.println("java.version: " + System.getProperty("java.runtime.version"));
        int shortcutKeyMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
        
        JFrame frame = new JFrame("ScreenMenuBar LAF: " + UIManager.getLookAndFeel().getName());
        frame.setSize(300, 300);
        
        // create a menubar with one menu and one menu item
        JMenuBar mb = new ScreenJMenuBar();
        JMenu menu = new JMenu("Test");
        mb.add(menu);
        JMenuItem mi = new JMenuItem(new AbstractAction("A Menu Item")
        {
            @Override
            public void actionPerformed(ActionEvent arg0)
            {
                // show a message when action is fired
                JOptionPane.showMessageDialog(null, "Menu Item selected: <" + arg0.getActionCommand()+">");
            }
        });
        // assign a keystroke
        mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, shortcutKeyMask));
        menu.add(mi);
        frame.setJMenuBar(mb);
        
        frame.setVisible(true);
    }
    
    public static void main(String[] args)
    {
        // on macOS show menubar as ScreenMenuBar
        System.setProperty("apple.laf.useScreenMenuBar", "true");
        UIManager.getInstalledLookAndFeels(); // needed to prevent "java.lang.UnsatisfiedLinkError: com.apple.laf.ScreenMenu.addMenuListeners"
        try
        {
            // use non "Mac OS X" LookAndFeel
            UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

        javax.swing.SwingUtilities.invokeLater(new Runnable() 
        {
            public void run() 
            {
                createAndShowGUI();
            }
        }); 
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
add "--add-exports java.desktop/com.apple.laf=ALL-UNNAMED", which is not recommended.


Comments
The issue is misunderstood. The question is how to make it available.
27-09-2016

This is not expected behavior because, when Aqua LAF is set, the native menubar is set and since this menubar is OS provided and that LAF is a closed module within java.desktop. This can not be changed.
27-09-2016

This is a restriction of the JDK 9 module system. In 9 you can do the L&F instantiation by calling UIManager.createLookAndFeel(UIManager.getSystemLookAndFeelClassName()); http://download.java.net/java/jdk9/docs/api/javax/swing/UIManager.html#createLookAndFeel-java.lang.String- If you also need to access AquaMenuBarUI then that is still protected and that may need some work and perhaps decoupling from Aqua
19-09-2016