[
https://issues.apache.org/jira/browse/GROOVY-12223?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18101028#comment-18101028
]
ASF GitHub Bot commented on GROOVY-12223:
-----------------------------------------
testlens-app[bot] commented on PR #2755:
URL: https://github.com/apache/groovy/pull/2755#issuecomment-5156758705
## 🚨 TestLens detected 2 failed tests 🚨
Here is what you can do:
1) Inspect the test failures carefully.
2) If you are convinced that some of the tests are flaky, you can mute them
below.
3) Finally, trigger a rerun by checking the rerun checkbox.
### Test Summary
#### [Build and test / lts \(17,
macos-latest\)](https://github.com/apache/groovy/actions/runs/30740350999/job/91476514334?pr=2755)
> :test
| Test | Runs | Flakiness |
|---|---|--:|
| HiddenClassDefinerTest > defineNestmateClass is a nestmate with weak
lifecycle\(\) | ❌ | 0% 🟢 |
| HiddenClassDefinerTest > hidden nestmate shares the nest with the lookup
class\(\) | ❌ | 0% 🟢 |
🏷️ Commit: 70b0e734c4f9ba366d1da6a867779b787995f0dc
▶️ Tests: 71149 executed
🟡 Checks: 9/29 completed
### Test Failures
<details>
<summary><strong>HiddenClassDefinerTest > defineNestmateClass is a nestmate
with weak lifecycle()</strong> (:test in <a
href="https://github.com/apache/groovy/actions/runs/30740350999/job/91476514334?pr=2755">Build
and test / lts (17, macos-latest)</a>)</summary>
```
org.opentest4j.AssertionFailedError: expected:
<org.apache.groovy.util.HiddenClassDefinerTest> but was:
<org.apache.groovy.util.HiddenClassDefinerTest$$InjectedInvoker/0x00000078014dd000>
at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1199)
at org.apache.groovy.util.HiddenClassDefinerTest.defineNestmateClass is
a nestmate with weak lifecycle(HiddenClassDefinerTest.groovy:165)
```
|expected|actual|
|---|---|
|class org.apache.groovy.util.<s>HiddenClassDefinerTest</s>|class
org.apache.groovy.util.<b>HiddenClassDefinerTest\$\$InjectedInvoker/0x00000078014dd000</b>|
</details>
<details>
<summary><strong>HiddenClassDefinerTest > hidden nestmate shares the nest
with the lookup class()</strong> (:test in <a
href="https://github.com/apache/groovy/actions/runs/30740350999/job/91476514334?pr=2755">Build
and test / lts (17, macos-latest)</a>)</summary>
```
org.opentest4j.AssertionFailedError: expected:
<org.apache.groovy.util.HiddenClassDefinerTest> but was:
<org.apache.groovy.util.HiddenClassDefinerTest$$InjectedInvoker/0x00000078014dd000>
at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1199)
at org.apache.groovy.util.HiddenClassDefinerTest.hidden nestmate shares
the nest with the lookup class(HiddenClassDefinerTest.groovy:127)
```
|expected|actual|
|---|---|
|class org.apache.groovy.util.<s>HiddenClassDefinerTest</s>|class
org.apache.groovy.util.<b>HiddenClassDefinerTest\$\$InjectedInvoker/0x00000078014dd000</b>|
</details>
### Muted Tests
> [!NOTE]
> Checks are currently running using the configuration below.
Select tests to mute in this pull request:
🔲 HiddenClassDefinerTest > defineNestmateClass is a nestmate with weak
lifecycle\(\) <!
> Introduce hidden class support
> ------------------------------
>
> Key: GROOVY-12223
> URL: https://issues.apache.org/jira/browse/GROOVY-12223
> Project: Groovy
> Issue Type: Improvement
> Reporter: Daniel Sun
> Priority: Major
>
> h2. Background
> Groovy generates many short-lived synthetic classes at runtime, including:
> * map/interface proxies ({{ProxyGeneratorAdapter}})
> * reflection dispatch helpers ({{Reflector}} / {{ReflectorLoader}})
> * per-class meta-method artifacts ({{ClassLoaderForClassArtifacts}})
> Today these are defined with {{ClassLoader#defineClass}} as ordinary *named*
> classes. That has three practical downsides:
> # *Name pollution* — the synthetic types are discoverable via
> {{Class.forName}} / {{ClassLoader#loadClass}}.
> # *Metaspace pressure* — their lifetime is tied to the defining class loader;
> long-running applications that generate many artifacts retain them until the
> loader itself is collected.
> # *Access friction* — without nest membership, generated code cannot share
> private access with the host class the way a true nestmate can.
> JDK 15 introduced *hidden classes* ([JEP 371|https://openjdk.org/jeps/371]):
> classes defined through {{Lookup#defineHiddenClass}} that are
> non-discoverable by name, may join an access-control nest ({{NESTMATE}}), and
> may be unloaded independently of the defining loader when not marked
> {{STRONG}}.
> Groovy 6 requires JDK 17+, so the API is always present on supported runtimes.
> h2. Proposal
> Centralise hidden-class definition behind a single utility and prefer it for
> the dynamic class-generation sites listed above, with a transparent fallback
> to the existing {{ClassLoader#defineClass}} path.
> h3. New API
> {{org.apache.groovy.util.HiddenClassDefiner}} — the only call-site that
> invokes {{Lookup#defineHiddenClass}}:
> * {{defineHiddenClass(lookup, bytes, initialize, nestmate, strong)}} — full
> control
> * {{defineNestmateClass(lookup, bytes, initialize)}} — nestmate + weak
> lifecycle (default for proxies / reflectors / artifacts)
> * {{defineStrongHiddenClass(lookup, bytes, initialize)}} — non-discoverable,
> loader-tied lifetime
> * helpers: {{privateLookupIn(hostClass)}}, {{findConstructor(hiddenClass,
> ...parameterTypes)}}
> Kill-switch (evaluated once at class-init for hot-path cost):
> {noformat}
> -Dgroovy.hidden.classes.disable=true
> {noformat}
> When disabled (or when private lookup / definition fails), callers fall back
> to defining a normal visible class.
> h3. Integration points
> || Site || Nest host || Preferred options || Fallback ||
> | {{ClassLoaderForClassArtifacts#define}} | target (klazz) | nestmate, weak |
> {{ClassLoader#defineClass}} + protection domain |
> | {{ProxyGeneratorAdapter}} | non-{{Object}} superclass if present; else
> {{ProxyGeneratorAdapter}} | nestmate, weak | {{InnerLoader#defineClass}} |
> | {{ReflectorLoader#defineClass}} | {{Reflector}} | nestmate, weak |
> {{ClassLoader#defineClass}} + protection domain |
> Behaviour for callers of these generators is unchanged: proxies still
> implement the requested interfaces, reflectors still dispatch, artifacts
> still construct. The only observable differences when the hidden path
> succeeds are the synthetic name form (contains {{/}}) and {{Class#isHidden()
> == true}}.
> h2. Benefits
> * Non-discoverable synthetic types (cleaner class-space / tooling view).
> * Nestmate private access where the nest host can be opened for private
> lookup.
> * Eager unloading of weak hidden classes reduces long-run metaspace retention
> for short-lived proxies and artifacts.
> * One policy / upgrade point if future JDKs add further
> {{Lookup.ClassOption}} values.
> h2. Compatibility
> * Default-on when the JVM can obtain a full-privilege lookup for the chosen
> nest host; silent fallback otherwise (e.g. sealed / unopened module packages).
> * Opt-out: {{-Dgroovy.hidden.classes.disable=true}}.
> * No public language-surface change; no change to successful proxy /
> reflector / artifact *behaviour*, only to how the {{Class}} is defined.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)