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. 
            } 
        } 
    } 
} 
