[
https://issues.apache.org/jira/browse/GROOVY-11841?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18052146#comment-18052146
]
ASF GitHub Bot commented on GROOVY-11841:
-----------------------------------------
codecov-commenter commented on PR #2367:
URL: https://github.com/apache/groovy/pull/2367#issuecomment-3755377826
##
[Codecov](https://app.codecov.io/gh/apache/groovy/pull/2367?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
Report
:white_check_mark: All modified and coverable lines are covered by tests.
:white_check_mark: Project coverage is 67.0191%. Comparing base
([`d0a53bd`](https://app.codecov.io/gh/apache/groovy/commit/d0a53bd33ca7c72de989f1da50fd3dec33fc4cee?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache))
to head
([`db96c92`](https://app.codecov.io/gh/apache/groovy/commit/db96c928511f56037fa16aa25cab35cd01faccba?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)).
<details><summary>Additional details and impacted files</summary>
[](https://app.codecov.io/gh/apache/groovy/pull/2367?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
```diff
@@ Coverage Diff @@
## master #2367 +/- ##
==================================================
- Coverage 67.0225% 67.0191% -0.0034%
+ Complexity 29420 29416 -4
==================================================
Files 1382 1382
Lines 116152 116146 -6
Branches 20465 20466 +1
==================================================
- Hits 77848 77840 -8
- Misses 31814 31815 +1
- Partials 6490 6491 +1
```
| [Files with missing
lines](https://app.codecov.io/gh/apache/groovy/pull/2367?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
| Coverage Δ | |
|---|---|---|
|
[src/main/java/groovy/lang/MetaClassImpl.java](https://app.codecov.io/gh/apache/groovy/pull/2367?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Fgroovy%2Flang%2FMetaClassImpl.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3JjL21haW4vamF2YS9ncm9vdnkvbGFuZy9NZXRhQ2xhc3NJbXBsLmphdmE=)
| `77.9806% <100.0000%> (-0.0183%)` | :arrow_down: |
... and [2 files with indirect coverage
changes](https://app.codecov.io/gh/apache/groovy/pull/2367/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
</details>
<details><summary> :rocket: New features to boost your workflow: </summary>
- :snowflake: [Test
Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests,
report on failures, and find test suite problems.
- :package: [JS Bundle
Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save
yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
> Metaclass Concurrency Problem
> -----------------------------
>
> Key: GROOVY-11841
> URL: https://issues.apache.org/jira/browse/GROOVY-11841
> Project: Groovy
> Issue Type: Bug
> Affects Versions: 4.0.0
> Reporter: James Daugherty
> Priority: Blocker
> Attachments: image-2026-01-14-15-59-59-400.png
>
>
> I'm upgrading a highly concurrent application that uses Spring Batch to
> read/write data in parallel. After upgrading to Groovy 4, I'm seeing stack
> traces like this:
> {code:java}
> java.util.ConcurrentModificationException
> at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1221)
> at groovy.lang.MetaClassImpl.getMetaProperty(MetaClassImpl.java:308)
> at
> org.grails.datastore.mapping.reflect.ClassPropertyFetcher.getStaticPropertyValuesFromInheritanceHierarchy(ClassPropertyFetcher.java:229)
> at
> org.grails.datastore.mapping.reflect.ClassPropertyFetcher.getStaticPropertyValuesFromInheritanceHierarchy(ClassPropertyFetcher.java:219)
> at
> org.grails.datastore.gorm.validation.constraints.eval.DefaultConstraintEvaluator.evaluate(DefaultConstraintEvaluator.java:116)
> at
> org.grails.datastore.gorm.validation.constraints.eval.DefaultConstraintEvaluator.evaluate(DefaultConstraintEvaluator.java:111)
> at
> org.grails.datastore.gorm.validation.constraints.eval.DefaultConstraintEvaluator.evaluate(DefaultConstraintEvaluator.java:106)
> at
> grails.gorm.validation.PersistentEntityValidator.<init>(PersistentEntityValidator.groovy:71)
> at
> org.grails.datastore.gorm.validation.constraints.registry.DefaultValidatorRegistry.getValidator(DefaultValidatorRegistry.groovy:85)
> at
> org.grails.datastore.gorm.validation.jakarta.JakartaValidatorRegistry.getValidator(JakartaValidatorRegistry.groovy:127)
> at
> org.grails.datastore.mapping.model.AbstractMappingContext.getEntityValidator(AbstractMappingContext.java:219)
> at
> org.grails.datastore.gorm.GormValidationApi.getValidator(GormValidationApi.groovy:82)
> at
> org.grails.orm.hibernate.AbstractHibernateGormValidationApi.validate(AbstractHibernateGormValidationApi.groovy:61)
> at
> org.grails.orm.hibernate.AbstractHibernateGormValidationApi.validate(AbstractHibernateGormValidationApi.groovy:55)
> at
> org.grails.datastore.gorm.GormValidateable$Trait$Helper.validate(GormValidateable.groovy:76)
> at
> com.triu.system.SystemDirectQuery.validate(SystemDirectQuery.groovy)
> at
> org.grails.orm.hibernate.support.ClosureEventListener.doValidate(ClosureEventListener.java:306)
> at
> org.grails.orm.hibernate.support.ClosureEventListener$7.call(ClosureEventListener.java:272)
> at
> org.grails.orm.hibernate.support.ClosureEventListener$7.call(ClosureEventListener.java:261)
> at
> org.grails.orm.hibernate.support.ClosureEventListener.doWithManualSession(ClosureEventListener.java:385)
> at
> org.grails.orm.hibernate.support.ClosureEventListener.onPreUpdate(ClosureEventListener.java:261)
> at
> org.grails.orm.hibernate.event.listener.HibernateEventListener.onPreUpdate(HibernateEventListener.java:158)
> {code}
>
>
> GROOVY-9631 replaced these data structures with LinkedHashmaps. A side
> effect of this is that code that previously executed concurrently without
> issue seems to be no longer thread safe.
> [https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/LinkedHashMap.html]
> has this warning too:
> {code:java}
> Note that this implementation is not synchronized.
> If multiple threads access a linked hash map concurrently, and at least
> one of the threads modifies the map structurally, it must be
> synchronized externally. This is typically accomplished by
> synchronizing on some object that naturally encapsulates the map.
> If no such object exists, the map should be "wrapped" using the
> Collections.synchronizedMap
> method. This is best done at creation time, to prevent accidental
> unsynchronized access to the map:{code}
> It makes sense to lock down writes to maps, but since the read is non-thread
> safe it seems this could still be problematic.
>
>
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)