Paul King created GROOVY-12281:
----------------------------------

             Summary: Investigate mitigating class-loader pinning by 
ClassInfo.globalClassValue under the default ClassValue implementation
                 Key: GROOVY-12281
                 URL: https://issues.apache.org/jira/browse/GROOVY-12281
             Project: Groovy
          Issue Type: Improvement
            Reporter: Paul King


Follow-up from review discussion on [PR 
#2798|https://github.com/apache/groovy/pull/2798] (GROOVY-12142), preserving 
the analysis from that review. A {{ClassValue}} realizes the chain _key class → 
association → value → everything reachable from it_, and the association lives 
as long as the key class 
([JDK-8136353|https://bugs.openjdk.org/browse/JDK-8136353], working as 
intended). The {{ClassValue}} implementation class itself prevents no 
unloading; what matters is the key's origin: a Groovy-loaded key class dies 
with Groovy's loader (fine), but a JDK/platform key class is effectively 
immortal, so any value reachable from it that was loaded by Groovy's loader 
pins that loader forever. Indirection counts — a JDK-typed value (e.g. an 
{{ArrayList}}) whose _elements_ are Groovy-loaded re-creates the pin one level 
down.

{{ClassInfo.globalClassValue}} is static with unknown keys, including platform 
classes ({{String}} receives a {{ClassInfo}} in essentially every Groovy 
program), so the default {{ClassValue}} path pins the loader; today's only 
remedy is the global {{groovy.use.classvalue=false}} escape hatch, which trades 
away the per-class fast path for all keys.

The general mitigation — {{SoftReference}}-wrapped values with a 
check-remove-recompute protocol — requires that recomputation be legal, and for 
{{ClassInfo}} it is not in general: a {{ClassInfo}} can carry non-recomputable 
state (modified metaclasses, category state), so a softly-collected value could 
silently discard user metaclass customizations. Approaches to investigate:
* soft values while a {{ClassInfo}} is pristine, hardening the reference on 
first mutation — only classes with customized metaclasses would then pin, a far 
smaller set;
* per-key policy: platform-loader keys get soft/map treatment, Groovy-loader 
keys stay strong (the key-origin rule applied mechanically);
* splitting {{ClassInfo}} into recomputable and stateful parts;
* revisiting whether the map-based implementation should become the default, 
with {{ClassValue}} as the opt-in fast path.

Recompute cost and dispatch-path performance need measurement for any candidate.




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to