On Sat, 25 Apr 2026 08:00:23 GMT, Jeremy Wood <[email protected]> wrote:

>> src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java line 93:
>> 
>>> 91:         if (accessible instanceof Component component) {
>>> 92:             addNotificationListeners(component);
>>> 93:             component.addPropertyChangeListener("ancestor", (e) -> {
>> 
>> My only question is: you are registering a new listener but when this 
>> listener is being removed? I understand that this happens in the CAccessible 
>> constructor and under normal circumstances component has only one 
>> CAccessible but that can change and in this case wouldn't it be a potential 
>> memory leak?
>
> That is a great question, and it's the heart of what I don't understand well 
> here. (It's also why my original draft (which was much more invasive) moved a 
> lot more logic into the `dispose` method.)
> 
> Further testing/exploration led me to believe the CAccessible object is never 
> intended to be discarded. It is created once and permanently linked to its 
> analog AccessibleContext in `getCAccessible`. (This is the only place where 
> `setNativeAXResource` is ever called in the codebase; it is _never_ nullified 
> to release the CAccessible for GC.)
> 
>> under normal circumstances component has only one CAccessible but that can 
>> change and in this case wouldn't it be a potential memory leak
> 
> Is this a hypothetical, or is there a specific usage pattern you're thinking 
> of (that I'd like to learn about)?
> 
> What event could lead us to uninstall this new "ancestor" PCL? I can't think 
> of a universal signal that tells us "we're ready to uninstall now", given 
> what I (think I) understand about how CAccessible's work.
> 
> ## Alternative Proposal
> 
> How about this alternative (borrowed from 
> [here](https://github.com/mickleness/swing-accessibility/blob/main/src/main/java/com/pump/ax/mac/FixChangingAncestor.java)):
> 
> We never add a PCL to any Component. Instead we listen to _all_ 
> COMPONENT_REMOVED events:
> 
> 
> static {
>     AWTEventListener componentRemovedListener = new AWTEventListener() {
>         @Override
>         public void eventDispatched(AWTEvent event) {
>             if (event.getID() == ContainerEvent.COMPONENT_REMOVED) {
>                 ContainerEvent containerEvent = (ContainerEvent) event;
>                 CAccessible ca = 
> getCAccessibleOnlyIfOneAlreadyExists(containerEvent.getChild());
>                 if (ca != null)
>                     ca.dispose();
>             }
>         }
>     };
>     Toolkit.getDefaultToolkit().addAWTEventListener(componentRemovedListener, 
> ContainerEvent.CONTAINER_EVENT_MASK);
> }
> 
> 
> Would this bypass concerns about memory leaks?

There is no "uninstalling" of the accessible peer since there is no event that 
tells us that we are no longer in use by the accessibility system, i am mostly 
concerned for some code path that creates and replaces the accessible peer with 
the new one - the old one will be referenced by the PCL. That is more of the 
theoretical question - but i think i like the global listener approach more.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/30578#discussion_r3242674221

Reply via email to