You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2026/09/15 17:21:55 UTC
(juneau) branch master updated: Publish ClassMeta into the marshaller cache only after swaps is assigned so concurrent Html.of never observes a half-constructed instance (Jenkins Java-17 concurrency 500).
This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new 0002c9410c Publish ClassMeta into the marshaller cache only after swaps is assigned so concurrent Html.of never observes a half-constructed instance (Jenkins Java-17 concurrency 500).
0002c9410c is described below
commit 0002c9410c7390e632d09197afdd3aabaeb92d60
Author: James Bognar <ja...@apache.org>
AuthorDate: Tue Sep 15 13:21:49 2026 -0400
Publish ClassMeta into the marshaller cache only after swaps is assigned so concurrent Html.of never observes a half-constructed instance (Jenkins Java-17 concurrency 500).
---
.../src/main/java/org/apache/juneau/marshall/ClassMeta.java | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/ClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/ClassMeta.java
index 73c981b27f..1f82033561 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/ClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/ClassMeta.java
@@ -186,10 +186,6 @@ public final class ClassMeta<T> extends BeanInfo<T> {
this.marshallingContext = marshallingContext;
this.cat = new Categories();
- // We always immediately add this class meta to the bean context cache so that we can resolve recursive references.
- if (nn(marshallingContext) && nn(marshallingContext.getCmCache()) && isCacheable(innerClass))
- marshallingContext.getCmCache().put(innerClass, this);
-
var ap = marshallingContext.getAnnotationProvider();
if (isAssignableTo(Delegate.class)) {
@@ -272,6 +268,12 @@ public final class ClassMeta<T> extends BeanInfo<T> {
swaps = memoize(this::findSwaps);
this.args = null;
+
+ // Publish after fields are assigned so concurrent getClassMeta callers never observe
+ // this instance with swaps == null. Recursive bean-property lookups still resolve:
+ // they run from the lazy suppliers after construction, once this entry is cached.
+ if (nn(marshallingContext) && nn(marshallingContext.getCmCache()) && isCacheable(innerClass))
+ marshallingContext.getCmCache().put(innerClass, this);
}
protected ObjectSwap<?,?> findSwap(Class<?> c) {