JDK-8229821 : [macos] IllegalArgumentException thrown when unplugging external monitor
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 8u221,11.0.4,12.0.2,13,14
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: os_x
  • CPU: x86
  • Submitted: 2019-07-24
  • Updated: 2019-08-16
  • Resolved: 2019-08-16
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 14
14Resolved
Related Reports
Duplicate :  
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
MacBook Pro (13-inch, 2018, Four Thunderbolt 3 Ports)
macOS Mojave 10.14.5 (18F132)
openjdk version "11.0.4" 2019-07-16
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.4+11)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.4+11, mixed mode)

A DESCRIPTION OF THE PROBLEM :
When changing displays an IllegalArgumentException may be thrown.

This occurs because java.awt.GraphicsConfiguration#getBounds may return a zero width and height Rectangle which causes javax.swing.RepaintManager#getDoubleBufferMaximumSize to return a Dimension with a zero width and height. This gets passed into java.awt.GraphicsConfiguration#createCompatibleVolatileImage(int, int, java.awt.ImageCapabilities, int) which will fail when it creates a new sun.awt.image.SunVolatileImage.

We are seeing a lot of bug reports from our users about this issue. Whatever they are doing they seem to be encountering this bug a lot. The only way that I have been able to reproduce it is by plugging in an external monitor into my laptop, closing the laptop lid, then unplugging the external monitor. Upon unplugging the external monitor is when java.awt.GraphicsConfiguration#getBounds returns a zero width and height Rectangle.

This bug also seems to be present on Java 12 however the NullPointerException from bug 9061686 is obscuring it.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Run the main class Main on a laptop
2. Plug in an external monitor
3. Close the lid of the laptop
4. Unplug the external monitor
5. Reopen the lid of the laptop

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
There should be no exceptions.
ACTUAL -
One or more of the following exceptions will be thrown:

java.lang.IllegalArgumentException: Width (0) and height (0) cannot be <= 0
	at java.desktop/sun.awt.image.SunVolatileImage.<init>(SunVolatileImage.java:75)
	at java.desktop/sun.awt.image.SunVolatileImage.<init>(SunVolatileImage.java:122)
	at java.desktop/java.awt.GraphicsConfiguration.createCompatibleVolatileImage(GraphicsConfiguration.java:307)
	at java.desktop/java.awt.GraphicsConfiguration.createCompatibleVolatileImage(GraphicsConfiguration.java:241)
	at java.desktop/javax.swing.RepaintManager.getVolatileOffscreenBuffer(RepaintManager.java:1098)
	at Main.reproduceExceptionLoop(Main.java:95)
	at Main.main(Main.java:14)

java.lang.IllegalArgumentException: Width (0) and height (0) cannot be <= 0
	at java.desktop/sun.awt.image.SunVolatileImage.<init>(SunVolatileImage.java:75)
	at java.desktop/sun.awt.image.SunVolatileImage.<init>(SunVolatileImage.java:122)
	at java.desktop/java.awt.GraphicsConfiguration.createCompatibleVolatileImage(GraphicsConfiguration.java:307)
	at java.desktop/java.awt.GraphicsConfiguration.createCompatibleVolatileImage(GraphicsConfiguration.java:241)
	at java.desktop/javax.swing.RepaintManager.getVolatileOffscreenBuffer(RepaintManager.java:1098)
	at java.desktop/javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1543)
	at java.desktop/javax.swing.RepaintManager.paint(RepaintManager.java:1323)
	at java.desktop/javax.swing.JComponent._paintImmediately(JComponent.java:5203)
	at java.desktop/javax.swing.JComponent.paintImmediately(JComponent.java:5013)
	at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:865)
	at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:848)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
	at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:848)
	at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:823)
	at java.desktop/javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:772)
	at java.desktop/javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1890)
	at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:313)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
	at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

---------- BEGIN SOURCE ----------
import javax.swing.*;
import java.awt.*;
import java.io.PrintWriter;
import java.io.Writer;
import java.time.LocalDateTime;
import java.util.ConcurrentModificationException;

public class Main {

    private static volatile JTextArea ERRORS;

    public static void main(String[] args) {
        final JFrame gui = createAndShowGUI();
        reproduceExceptionLoop(gui);
    }

    private static JFrame createAndShowGUI() {
        final JFrame frame = new JFrame("Swing IllegalArgumentException");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setMinimumSize(new Dimension(500, 500));

        final JTextArea instructions = new JTextArea("Steps to reproduce:\n"
                + "1) Run this application on a laptop\n"
                + "2) Plug in an external monitor\n"
                + "3) Shut the lid of the laptop\n"
                + "4) Unplug the external monitor\n"
                + "5) Reopen the lid of the laptop");
        instructions.setMaximumSize(instructions.getPreferredSize());
        instructions.setEditable(false);

        final JLabel errorLabel = new JLabel("Uncaught exceptions:");

        ERRORS = new JTextArea();
        ERRORS.setEditable(false);

        final JScrollPane errorsPane = new JScrollPane(ERRORS);

        Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
            final LocalDateTime now = LocalDateTime.now();
            SwingUtilities.invokeLater(() -> {
                ERRORS.append(now.toString());
                ERRORS.append("Thread: " + t.toString() + "\n");
                ERRORS.append("Exception: ");
                e.printStackTrace(new PrintWriter(new Writer() {
                    @Override
                    public void write(char[] cbuf, int off, int len) {
                        ERRORS.append(String.copyValueOf(cbuf, off, len));
                    }

                    @Override
                    public void flush() {
                    }

                    @Override
                    public void close() {
                    }
                }));
                ERRORS.append("\n\n");
            });
            System.err.println(now.toString());
            e.printStackTrace();
        });

        final Container contentPane = frame.getContentPane();
        contentPane.add(instructions);
        contentPane.add(errorLabel);
        contentPane.add(errorsPane);

        final SpringLayout layout = new SpringLayout();
        contentPane.setLayout(layout);
        layout.putConstraint(SpringLayout.WEST, instructions, 5, SpringLayout.WEST, contentPane);
        layout.putConstraint(SpringLayout.EAST, instructions, -5, SpringLayout.EAST, contentPane);
        layout.putConstraint(SpringLayout.NORTH, instructions, 5, SpringLayout.NORTH, contentPane);
        layout.putConstraint(SpringLayout.WEST, errorLabel, 5, SpringLayout.WEST, contentPane);
        layout.putConstraint(SpringLayout.NORTH, errorLabel, 5, SpringLayout.SOUTH, instructions);
        layout.putConstraint(SpringLayout.WEST, ERRORS, 0, SpringLayout.WEST, errorsPane);
        layout.putConstraint(SpringLayout.NORTH, ERRORS, 0, SpringLayout.SOUTH, errorsPane);
        layout.putConstraint(SpringLayout.EAST, ERRORS, -0, SpringLayout.EAST, errorsPane);
        layout.putConstraint(SpringLayout.SOUTH, ERRORS, -0, SpringLayout.SOUTH, errorsPane);
        layout.putConstraint(SpringLayout.WEST, errorsPane, 5, SpringLayout.WEST, contentPane);
        layout.putConstraint(SpringLayout.NORTH, errorsPane, 5, SpringLayout.SOUTH, errorLabel);
        layout.putConstraint(SpringLayout.EAST, contentPane, 5, SpringLayout.EAST, ERRORS);
        layout.putConstraint(SpringLayout.SOUTH, contentPane, 5, SpringLayout.SOUTH, ERRORS);

        frame.pack();
        frame.setVisible(true);

        return frame;
    }

    private static void reproduceExceptionLoop(Component component) {
        while (true) {
            final RepaintManager repaintManager = RepaintManager.currentManager(component);
            setupPreconditions(repaintManager);
            repaintManager.getVolatileOffscreenBuffer(component, component.getWidth(), component.getHeight());
        }
    }

    private static void setupPreconditions(RepaintManager repaintManager) {
        while (true) {
            try {
                repaintManager.setDoubleBufferMaximumSize(null);
                return;
            } catch (ConcurrentModificationException e) {
                // Try again.
            }
        }
    }
}

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

FREQUENCY : occasionally



Comments
The zero bounds and IllegalArgumentException reported here were fixed as part of JDK-8211992. The NPE will be fixed as part of JDK-8229810
16-08-2019

Fails on 10.14.6 running 13-ea+33 on a MacBook Pro (13-inch, 2019, Four Thunderbolt 3 ports) as soon as the additional monitor is plugged in: java.lang.NullPointerException at java.desktop/sun.awt.CGraphicsDevice.getBounds(CGraphicsDevice.java:110) at java.desktop/sun.awt.CGraphicsConfig.getBounds(CGraphicsConfig.java:51) at java.desktop/javax.swing.RepaintManager.getDoubleBufferMaximumSize(RepaintManager.java:1212) at java.desktop/javax.swing.RepaintManager.getVolatileOffscreenBuffer(RepaintManager.java:1087) at Main.reproduceExceptionLoop(Main.java:95) at Main.main(Main.java:14)
16-08-2019

Reported with OpenJDK 11.0.4 in macOS 10.14.5 change in display throw an IllegalArgumentException. When checked on macOS 10.13.5, the issue does reproduce with reported versions 11.0.4 and 12.0.2, but it seems resolved in JDK 13 and 14 ea builds. However, it throws exceptions with JDK 8u221. However, this still need to be checked for macOS 10.14.5. Result: ========== 8u221: Fail 11.0.4: Fail 12.0.2: Fail 13 ea b33: OK 14 ea b10: OK Run with JDK 12.0.2: > java.lang.NullPointerException at java.desktop/sun.awt.CGraphicsDevice.getBounds(CGraphicsDevice.java:116) at java.desktop/sun.awt.CGraphicsConfig.getBounds(CGraphicsConfig.java:57) at java.desktop/javax.swing.RepaintManager.getDoubleBufferMaximumSize(RepaintManager.java:1212) at java.desktop/javax.swing.RepaintManager.getVolatileOffscreenBuffer(RepaintManager.java:1087) at Main.reproduceExceptionLoop(Main.java:95) at Main.main(Main.java:14) Run with JDK 11.0.4: >java.lang.IllegalArgumentException: Width (0) and height (0) cannot be <= 0 at java.desktop/sun.awt.image.SunVolatileImage.<init>(SunVolatileImage.java:75) at java.desktop/sun.awt.image.SunVolatileImage.<init>(SunVolatileImage.java:122) at java.desktop/java.awt.GraphicsConfiguration.createCompatibleVolatileImage(GraphicsConfiguration.java:307) at java.desktop/java.awt.GraphicsConfiguration.createCompatibleVolatileImage(GraphicsConfiguration.java:241) at java.desktop/javax.swing.RepaintManager.getVolatileOffscreenBuffer(RepaintManager.java:1098) at Main.reproduceExceptionLoop(Main.java:95) at Main.main(Main.java:14)
16-08-2019