Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8145984

[macosx] sun.lwawt.macosx.CAccessible leaks

    Details

      Backports

        Description

        When a11y is in action and CAccessible objects get created they don't go away as expected and are kept held by a native code via JNIGlobalRef, at the same time leaking a peered Component (along with its whole hierarchy) via the CAccessible.accessible field.

        It can be easily reproducible with the following test case and some memory profiler (like NB or YourKit).

        1) Compile and run it with the profiler. A frame with a button appears.
        2) Activate VoiceOver a11y tool (CMD+F5).
        3) Press the button. A dialog with a text field appears.
        4) Press ENTER, the dialog gets disposed.
        5) Keep pressing the button and then ENTER for a number of times (~10).

        Expected behavior:

        All Dialog instances should be GC'ed (force GC in the profiler) when no dialog is shown.

        Actual behavior:

        Instances of the following classes are tracked in the memory dump: Dialog, JTextField, AccessibleJTextField, CAccessible. The latter is kept by a JNIGlobalRef.

        ----------------------------
        import javax.swing.*;
        import java.awt.*;

        public class Main {

            public static void main(String[] args) {
                EventQueue.invokeLater(() -> {
                    final JFrame frame = new JFrame("AX");
                    JButton button = new JButton("open");
                    button.addActionListener((e) -> {
                        new MyDialog(frame).setVisible(true);
                    });
                    frame.add(button);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                });
            }
        }

        class MyDialog extends Dialog {

            private static int counter;

            public MyDialog(Frame owner) {
                super(owner, "Dialog");
                JTextField textField = new JTextField("" + ++counter);
                add(textField);
                textField.addActionListener((e) -> {
                    MyDialog.this.dispose();
                });
                pack();
                setLocationRelativeTo(null);
            }
        }
        ----------------------------

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  ant Anton Tarasov
                  Reporter:
                  ant Anton Tarasov
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  4 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved: