Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ObjectMapper default heap consumption increased significantly from 2.13.x to 2.14.0 #3665

Closed
mhalbritter opened this issue Nov 15, 2022 · 46 comments
Milestone

Comments

@mhalbritter
Copy link

mhalbritter commented Nov 15, 2022

Hello,

I'm currently looking at heap consumption when using native image with a Spring Boot 3 application. Spring Boot 3.0 SNAPSHOT uses Jackson 2.14.0-rc3. I noticed that with the upgrade from 2.13.4.2 to 2.14.0 the application uses more heap memory, which i tracked down to this PR. It changed the cache implementation from ConcurrentHashMap to PrivateMaxEntriesMap, which in turn preallocates a lot of AtomicReference (they appear to be all empty).

I created a reproducer here - it creates an empty objectmapper and then dumps the heap. It has more information and screenshots in the README.

When using Jackson 2.13.4.2 it uses 567 B for the LRUmap, with Jackson 2.14.0 it uses 507320 B for the LRU map. The bad thing is that most of these caches are per ObjectMapper - create more of them and it uses even more heap.

As we're trying to optimize the memory consumption of native image applications, this is quite a bummer and we hope you can help us out here.

Thanks!

@mhalbritter mhalbritter added the to-evaluate Issue that has been received but not yet evaluated label Nov 15, 2022
@mhalbritter
Copy link
Author

mhalbritter commented Nov 15, 2022

You can see the problem (but not as exaggerated) on a regular JVM. I created 100 ObjectMapper and heapdumped.

This is 2.13.4.2:

image

The usage is negligible.

This is 2.14.0:

image

The LRUmap uses 82.1% of the heap.

@GedMarc
Copy link

GedMarc commented Nov 15, 2022

From my understanding, ObjectMapper's should be singleton's as much as possible,
and the ObjectReader and ObjectWriters are the thread-safe objects that can be built from it -

So this would be a bad implementation of using the ObjectMapper

We use native imaging throughout and don't experience anything like this when it's used properly

@mhalbritter
Copy link
Author

mhalbritter commented Nov 15, 2022

I created 100 ObjectMappers to show the extent of this problem. As you'll see in https://github.com/mhalbritter/graalvm-jackson, it is even observable with only 1 ObjectMapper. 2.14.0 uses ~880x more heap for an empty ObjectMapper compared to 2.13.4.2.

Spring Boot in my WebMVC sample app uses 4 of them. Not sure if we can get this down to 1.

@GedMarc
Copy link

GedMarc commented Nov 15, 2022

Hmmm - @cowtowncoder this one needs your eyes

@sdeleuze
Copy link

I agree with @mhalbritter, it looks like the heap allocation regression in 2.14 is pretty huge and I hope that something could be refined on Jackson side.

@cowtowncoder Looking forward to your feedback, we still have the opportunity to update Jackson before Spring Boot 3 GA is released (expected next week).

@cowtowncoder
Copy link
Member

cowtowncoder commented Nov 16, 2022

Uh. I did have some concerns about apparent complexity of the improved cache choice, relative to benefits. The baseline for cache should be solid from what I recall, but @pjfanning worked on it most closely.

This is unfortunate of course. But just to make sure: that's about 0.5 MB per ObjectMapper, without any use? (basic data structures).

Given timing I suspect the only potentially easyish win would be changing initial size? And even that would require 2.14.1 release.

@cowtowncoder cowtowncoder changed the title Heap consumption regression from 2.13.4.2 to 2.14.0 ObjectMapper default heap consumption increased significantly from 2.13.x to 2.14.0 Nov 16, 2022
@cowtowncoder
Copy link
Member

Ok, looks like there are just 4 cache instances by default (plus one optional):

  1. JacksonAnnotationIntrospector uses it to keep track of annotations that have (or not) JacksonAnnotationsInside. This definitely does not need super-nice cache
  2. TypeFactory caches types; this is relatively heavily used during construction of (de)serializers
  3. SerializerCache probably the most important cache since many serializers are dynamically accessed
  4. DeserializerCache somewhat important but deserializers mostly statically accessed beyond root instances
  5. (optional) RootNameLookup -- mostly used with XML, sometimes JSON

Initial sizes of all these seem to be between 16 and 65, nothing drastic unless I am missing something.

It would be good to get more numbers, if possible, on sizes of individual LRUMap instances.
Unfortunately it doesn't look like initial sizes can be reduced a lot (or put another way, reducing would not have humongous effect).
It'd also be good to just have an estimate of a single LRUMap with specific initial size as baseline to consider what exactly to do. The whole PrivateMaxEntriesMap implementation seems very much overpowered for Jackson's use case... and it'd be good to see if some parts could be removed.

@ben-manes
Copy link

Sorry, I haven’t looked at that caching logic for about 7 years (or 12 when written). At the time the emphasis was concurrency for server-class usages, when a concurrent lru algorithm was a novel, hard problem. I’m sure those AtomicReferences could be replaced by aAtomicReferenceArray to slim it down. It is striped lanes to reduce thread contention, but you could greatly simplify that by knowing what is actually needed here, e.g. a single array is probably fine.

I later rewrote this to dynamically stripe light weight, mpsc ring buffers. That is more memory conscious by being slimmer and demand based.

@ben-manes
Copy link

@bclozel may be interested as he similarly rewrote that original code for use by Spring. There are versions floating around in groovy, mssql jdbc, etc. it should be simple to streamline to be more tuned towards the project needs.

@cowtowncoder
Copy link
Member

That sounds useful @ben-manes thank you for sharing. I wonder how easy it'd be to measure -- of course it's not rocket science to just count fields and do it manually but there are probably tools to automate using introspection to at least give static minimums or such.

@ben-manes
Copy link

I used openjdk’s object layout on the current code to verify padding rules for protecting against false sharing. And for a rough footprint estimate, jamm is good enough for seeing if things line up to expectations. All are just best guesses due to jvm internal complexity, JEP-8249196.

@mhalbritter
Copy link
Author

mhalbritter commented Nov 16, 2022

This is unfortunate of course. But just to make sure: that's about 0.5 MB per ObjectMapper, without any use? (basic data structures).

VisualVM tells me that 1 ObjectMapper on the JVM uses 132.352 B of heap. This is a new ObjectMapper() without doing anything more with it. However all LRUMap instances are 213.640 B of heap.

VisualVM tells me that 1 ObjectMapper in a native image uses 311.944 B of heap. However all LRUmap instances are 507.320 B of heap.

Here are all the LRUmap instances on the JVM with the fields which have a reference on them:

image

@mhalbritter
Copy link
Author

They are all the same size, because the AtomicReference[][] readBuffers field, which consumes most of the heap, is sized this way:

static final int NCPU = Runtime.getRuntime().availableProcessors(); // 9 on my machine
static final int NUMBER_OF_READ_BUFFERS = ceilingNextPowerOfTwo(NCPU); // 16 on my machine
static final int READ_BUFFER_THRESHOLD = 32;
static final int READ_BUFFER_DRAIN_THRESHOLD = 2 * READ_BUFFER_THRESHOLD; // 64
static final int READ_BUFFER_SIZE = 2 * READ_BUFFER_DRAIN_THRESHOLD; // 128

readBuffers = new AtomicReference[NUMBER_OF_READ_BUFFERS][READ_BUFFER_SIZE];

which will make this is a AtomicReference[16][128] array on my machine (this depends on the number of CPU cores). This is not influenced by initialCapacity or maximumCapacity as far as i can see.

@ben-manes
Copy link

Yes, concurrency is unrelated to a maximum cache size. At that time a synchronized lru was standard and perfectly fine in most cases due to single core machines still being common. Those who used this concurrent cache (ConcurrentLinkedHashMap) were servers that had clear needs (4-1024 cores). This led to porting into Guava (CacheBuilder) where we defaulted to 4 for Google’s needs, with a setting to adjust manually (concurrencyLevel). For a more general, modern cache (Caffeine) it now dynamically adjusts the size by need so that low concurrency has a low footprint while high concurrency benefits by trading some extra space. However CLHM is simpler to fork and embed, so decisions that aged poorly are copied over.

For Jackson a modest size is enough, thanks to lossy buffers and modest needs, so slimming this down should be simple and effective. Or if you prefer the advanced solution, copying that code and making the minor replacement edits.

@pjfanning
Copy link
Member

pjfanning commented Nov 16, 2022

The jackson-databind use case is to actually implement LRU behavior and not clear the whole cache when it fills (unlike 2.13-and-before implementation).

The use of PrivateMaxEntriesMap (a renamed fork of https://github.com/ben-manes/concurrentlinkedhashmap) is to be able to cap the entry size of the map and to evict the LRU instances when the entry size limit is reached.

We could certainly try to reduce the AtomicReference[][] readBuffers size to maybe max out as NUMBER_OF_READ_BUFFERS=4 and READ_BUFFER_THRESHOLD=4. We should set up some load test scenarios to see if those numbers are ok. Throwing unexpected exceptions is the main worry but also, we would like not to have poor performance in any usage scenarios. We could tweak these new numbers to see if they have a major impact.

@bclozel
Copy link

bclozel commented Nov 16, 2022

I've locally switched AtomicReference[] to AtomicReferenceArray and I'm seeing a nice improvement on heap consumption. In theory this shouldn't change things much for runtime performance but I'm seeing a degradation (but still in the error margin).

Right now Spring's implementation is not the dominator here, but we might still revisit the read buffer sizes or how its implementation works.

@cowtowncoder cowtowncoder added 2.14 and removed to-evaluate Issue that has been received but not yet evaluated labels Nov 16, 2022
@cowtowncoder
Copy link
Member

@pjfanning (I reworded your desc a bit) -- +1 for capping size of those arrays so that no matter how many cores it would not increase linearly.

@bclozel Use of AtomicReferenceArray sounds good as well.

Ultimately I think memory usage per cache should be significant lower than initial implementation. Load testing would be nice, but it is worth noting we didn't perf test new implementation vs old implementation either...

@ben-manes
Copy link

In theory this shouldn't change things much for runtime performance but I'm seeing a degradation

This is due to cpu cache line sharing which causes coherency bottlenecks as a distinct fields within a block are invalidated together. As the thread distribution is not perfect some shared producers will select the same lane. In a perfect world each slot would be fully padded so that once an index is acquired the two producers do not impact each other. That of course is very wasteful (64-byte blocks). The use of object references was a middle ground for partial padding. In these guava benchmarks from one of my attempts to revisit using ring buffers (uses CLQ as quick-and-dirty first pass), the read throughput ranged from 240M (64b) / 256M (256b) / 285M (1kb) ops/s. While the 45M spread sounds scary, in practice the cache reads won't be a bottleneck if it can support ~60M ops/s due to real application work so further gains won't impact system performance.

We should set up some load test scenarios to see if those numbers are ok.

Please see this jmh benchmark as a reference.

@pjfanning
Copy link
Member

16*128*4 (4 bytes per Java object pointer) means that the AtomicReference[16][128] readBuffers should use 8192 bytes (8 Kb). This seems a long way short of the totals being quoted for each ObjectMapper.

@ben-manes
Copy link

ben-manes commented Nov 16, 2022

@pjfanning you forgot to account for the AtomicReference instances themselves. That ranges from 16-32 bytes depending on the jvm optimizations (compressed references, compressed class pointers, byte alignment). In that case you might expect to see it as 16 * 128 (4 + 32) = 73,728 or ~300kb if each mapper uses 4 caches. Using Java Object Layout,

# Running 64-bit HotSpot VM.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
# WARNING | Compressed references base/shifts are guessed by the experiment!
# WARNING | Therefore, computed addresses are just guesses, and ARE NOT RELIABLE.
# WARNING | Make sure to attach Serviceability Agent to get the reliable addresses.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

... (many variations) ...

***** Hotspot Layout Simulation (JDK 15, 64-bit model, compressed class pointers, 16-byte aligned)
java.util.concurrent.atomic.AtomicReference object internals:
OFF  SZ               TYPE DESCRIPTION               VALUE
  0   8                    (object header: mark)     N/A
  8   4                    (object header: class)    N/A
 12   4                    (alignment/padding gap)
 16   8   java.lang.Object AtomicReference.value     N/A
 24   8                    (object alignment gap)
Instance size: 32 bytes
Space losses: 4 bytes internal + 8 bytes external = 12 bytes total

@cowtowncoder
Copy link
Member

300 kB sounds in the ballpark that was observed.

AtomicReferenceArray could improve things, but also seems like limiting actual size of 2-dimensional array (which @pjfanning suggested I think) would make sense.

I wonder how much we could cut things here -- to me some added overhead is fine; ObjectMapper instances will accumulate other baggage when actually used (for cached Serializers, Deserializers in particular).
But getting from ~300kB to less than 100kB would seem like a worthwhile goal to me.

@yawkat
Copy link
Member

yawkat commented Nov 17, 2022

i dont think it has to be a 2-dimensional array either, could save some space by flattening it.

@cowtowncoder
Copy link
Member

cowtowncoder commented Nov 17, 2022

@yawkat Going to AtomicReferenceArray would remove one dimension, although I guess it'd be possible to flatten both dimensions into single instance. Not sure if that'd be bad wrt false sharing or other caching aspects but that'd probably eliminate quite a bit of usage. And in some ways locality could help (but this is not my area of expertise TBH).

@ben-manes
Copy link

To be fair, since Jackson's caches are likely tiny a Clock (aka Second Chance) policy would be adequate if you wanted a much simpler rewrite. That was my original stop-gap when starting to explore a general approach. It is simply a FIFO with a mark bit that is set on a read and reset during an O(n) eviction scan. That has similar hit rates to an LRU with lock-free reads, but writes block on a shared lock and large caches have GC-like pauses due to scanning. For a small cache like I imagine these to be, anything simple (even just FIFO or random) is likely good enough. I think it would be perfectly fine to write a very simple, fast, low overhead cache that is specific to your needs.

@cowtowncoder
Copy link
Member

I have bit ambivalent feelings about this. On one hand, yes, use case specific would be good. On the other hand, using something (as close to) off-the-shelf (as possible) is great.
So in that sense, incremental changes for 2.14.x at least, to address unexpectedly sizable memory usage increase, would probably be best.
For 2.15 could do something bigger. Assuming we have someone with time and interest.

@cowtowncoder
Copy link
Member

Ok at this point I am optimistic about being able to optimize LRUMap implementation to have much lower memory footprint, so there's no need to revert change. Better cache pluggability/configuration would still be nice but that would require API change and go in at earliest in 2.15.

I wonder if use of jol for main ObjectMapper would help us guard against significant unintended memory usage increase for some changes -- just constructing an instance, testing direct size. And for bonus points do the same after one simple serialization, deserialization.
The idea being that limit for maximum size (on CI?) would be kept relatively tight and increased along with additional fields, but making it easier to notice increases that are higher than expected (including surprises where none were expected etc).

@yawkat
Copy link
Member

yawkat commented Nov 20, 2022

@cowtowncoder I tried to add exactly such a test (though the limit is fairly lax), but ran into these issues with JOL on CI: #3675 (comment)

@cowtowncoder
Copy link
Member

Fixed for 2.14.1.

@sdeleuze
Copy link

Awesome, thanks a lot for this quick update! Looking forward to leverage Jackson 2.14.1 asap available. If the release could happen by tomorrow (Nov 22), that would I think allow us to ship Spring Boot 3 GA with the memory fix.

@mhalbritter
Copy link
Author

Nice, thanks a lot!

@cowtowncoder
Copy link
Member

I'll see if I could find time today to release a patch version; cannot promise it but will try my best.

@cowtowncoder
Copy link
Member

Ta-dah! I did it. 2.14.1 release mostly done, last couple of artifacts on their way to Maven Central (Scala module may take bit longer). Please LMK if you find issues.

sdeleuze added a commit to sdeleuze/spring-framework that referenced this issue Nov 22, 2022
Fix an important memory consumption regression, see
FasterXML/jackson-databind#3665
for more details.

Closes spring-projectsgh-29539
srowen pushed a commit to apache/spark that referenced this issue Nov 23, 2022
### What changes were proposed in this pull request?
This pr aims upgrade `Jackson` related dependencies to 2.14.1

### Why are the changes needed?
This version include  an optimization of heap memory usage for Jackson 2.14.x:

- FasterXML/jackson-databind#3665

The full release notes as follows:

- https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.14.1

### Does this PR introduce _any_ user-facing change?
No

### How was this patch tested?
Pass GitHub Actions

Closes #38771 from LuciferYang/SPARK-41239.

Authored-by: yangjie01 <yangjie01@baidu.com>
Signed-off-by: Sean Owen <srowen@gmail.com>
@cowtowncoder
Copy link
Member

@yawkat MapperFootprintTest seems to be running for CI too and arbitrarily failing. I think I'll increase limit a bit for now, to at least reduce incidence rate.

@yawkat
Copy link
Member

yawkat commented Nov 28, 2022

@cowtowncoder ugh, or just disable it for now. ive given up on making the results resilient to gc, there is too much going on, weird caches with soft references and such. maybe it will be less flaky with epsilon gc, but that's not available on java 8 so i didn't try it for the ci

bclozel added a commit to spring-projects/spring-framework that referenced this issue Dec 5, 2022
Prior to this commit, the `ConcurrentLruCache` implementation would use
arrays of `AtomicReference` as operation buffers, and the buffer count
would be calculated with the nearest power of two for the CPU count.

This can result in significant heap memory usage as each
`AtomicReference` buffer entry adds to the memory pressure. As seen in
FasterXML/jackson-databind#3665, this can add a significant overhead for
no real added benefit for the current use case.

This commit changes the current implementation to use
`AtomicReferenceArray` as buffers and reduce the number of buffers.
JMH benchmarks results are within the error margin so we can assume that
this does not change the performance characteristics for the typical use
case in Spring Framework.

Fixes gh-29520
beliefer pushed a commit to beliefer/spark that referenced this issue Dec 15, 2022
### What changes were proposed in this pull request?
This pr aims upgrade `Jackson` related dependencies to 2.14.1

### Why are the changes needed?
This version include  an optimization of heap memory usage for Jackson 2.14.x:

- FasterXML/jackson-databind#3665

The full release notes as follows:

- https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.14.1

### Does this PR introduce _any_ user-facing change?
No

### How was this patch tested?
Pass GitHub Actions

Closes apache#38771 from LuciferYang/SPARK-41239.

Authored-by: yangjie01 <yangjie01@baidu.com>
Signed-off-by: Sean Owen <srowen@gmail.com>
beliefer pushed a commit to beliefer/spark that referenced this issue Dec 18, 2022
### What changes were proposed in this pull request?
This pr aims upgrade `Jackson` related dependencies to 2.14.1

### Why are the changes needed?
This version include  an optimization of heap memory usage for Jackson 2.14.x:

- FasterXML/jackson-databind#3665

The full release notes as follows:

- https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.14.1

### Does this PR introduce _any_ user-facing change?
No

### How was this patch tested?
Pass GitHub Actions

Closes apache#38771 from LuciferYang/SPARK-41239.

Authored-by: yangjie01 <yangjie01@baidu.com>
Signed-off-by: Sean Owen <srowen@gmail.com>
toneofrain added a commit to toneofrain/spring-framework that referenced this issue Dec 23, 2022
* Upgrade to Reactor 2020.0.25

See spring-projectsgh-29464

* Polish AOT ref docs

* Update testing chapter regarding Servlet 6.0 baseline for mocks

* Document TestSocketUtils in the testing chapter

* Fix Javadoc formatting issue in TestSocketUtils

* Revert "Ignore HttpComponents Javadoc"

This reverts commit f50b472.

HttpComponents Javadoc is available again.

See spring-projectsgh-29479
See https://issues.apache.org/jira/browse/HTTPCLIENT-2227

* Fix section formatting in the testing chapter

* Document AOT support in the TestContext framework

Closes spring-projectsgh-29482

* Assert fixed in DefaultErrorResponseBuilder

Fixed assert on wrong constructor fields

* Polish

* Align javadoc of DefaultParameterNameDiscoverer with its behavior

* Polishing deprecated methods

Added since and forRemoval to Deprecated methods.

* Add milestone repo for optional Netty 5 support

Closes spring-projectsgh-29498

* Next development version (v6.0.1-SNAPSHOT)

* Suppress "removal" warnings in CronSequenceGeneratorTests

* Polishing

* Fix Javadoc formatting issues for headings

Headings in method-level Javadoc must be h4 or higher in recent versions
of Java.

* Update Jackson-based decoders to reflect 2.14 baseline

See spring-projectsgh-29508

* Refactor Asciidoctor attributes in reference docs

This commit reorganizes the asciidoctor attributes for the reference
documentation. Instead of being contributed partially by the build and
individual documents, attributes are now shared in common files that are
included in top sections.

* Polishing

* Add callouts to Kotlin examples for parity

* Add missing callouts

* Work around code example callout bug

This commit adds callouts to two sets of Java/Kotlin code examples in
the @ModelAttribute section for Web MVC in order to work around the
"Code example has callout from a different code example" bug.

This also aligns the Web MVC examples with the WebFlux examples.

As a side note, the bug can also be seen in the WebFlux documentation
if the callouts are removed from the first Java/Kotlin examples in the
@ModelAttribute section for WebFlux. Thus it appears to be a general
issue related to examples within a given section of the documentation
when some examples have callouts and others do not, likely due to a bug
in the Javascript that provides this feature.

See spring-projectsgh-29505

* Polishing

* Generalize Jackson version numbers

This commit removes specific version info from Jackson codecs and
converters, in favor of generic info or removing the version information
all together.

See spring-projectsgh-29508

* Use lambda expression for Callable example in ref docs

* Document GraalVM substitutions upcoming removal

* Update documentation to mention Java 17+ baseline

Closes spring-projectsgh-29514

* Fix link to WebFlux section

Closes spring-projectsgh-29513

* Set error status in Observation Servlet filter

Prior to this commit, the Observation Servlet filter would record
unhandled exceptions on the observation context but would leave the
default HTTP response status as is.
Servlet containers do set the response status in that case to 500 by
default. Not doing that at the Servlet filter level results in invalid
observations, stating that the HTTP response status is 200 (because the
error status hasn't been set yet by the container) and as a result, the
outcome is SUCCESS.

This commit ensures that the error status is set in those cases,
aligning the behavior with Servlet containers.

Fixes spring-projectsgh-29512

* Polish AbstractAutowireCapableBeanFactory and use instanceof pattern matching

Closes spring-projectsgh-29499

* Polish contribution

* Polishing

* Polish asciidoc attributes

* Reorganize and modularize the Testing chapter in the reference manual

Closes spring-projectsgh-29522

* Document RuntimeHints testing strategies

Closes spring-projectsgh-29523

* Disable checkstyle for reference docs code snippets

* Fix broken link to Web MVC Testing section

* Remove TODOs in WebFlux ref docs

* Polishing

* Fix link to WebFlux section in reference manual

Closes spring-projectsgh-29525

* Introduce appendix in Testing chapter in the reference manual

This commit moves the Annotations and Further Resources sections to the
new Appendix.

See spring-projectsgh-29522

* Reinstate `chapter` asciidoc attribute for Web MVC

* Polish asciidoc attributes

* Ensure source code in framework-docs is compiled in the build

This also ensures that the source code can be properly imported into an
IDE.

* Polish ref docs

- stop referring to Java Config as new
- stop referring to Struts 2.x as if it were new
- polish AOT documentation
- etc.

* Polish ref docs

* Ensure code listing callouts are displayed incorrectly in core-beans.adoc

Closes spring-projectsgh-29457

* Fix a syntax error in an XML listing by adding a missing double-quote

Closes spring-projectsgh-29456

* Update LogAdapter to allow build-time code removal

Allow for example to remove those classes and 90 related methods when Logback is used:
- org.apache.commons.logging.LogAdapter$JavaUtilAdapter
- org.apache.commons.logging.LogAdapter$JavaUtilLog
- org.apache.commons.logging.LogAdapter$LocationResolvingLogRecord
- org.apache.commons.logging.LogAdapter$Log4jAdapter
- org.apache.commons.logging.LogAdapter$Log4jLog
- org.apache.commons.logging.LogAdapter$LogApi
- org.apache.logging.log4j.message.ObjectMessage
- org.apache.logging.log4j.message.ReusableObjectMessage
- org.apache.logging.log4j.simple.SimpleLoggerContext
- org.apache.logging.log4j.simple.SimpleLoggerContextFactory

Closes spring-projectsgh-29506

* Do not use LocalVariableTableParameterNameDiscoverer in AOT mode

Closes spring-projectsgh-29531

* Revert "Ensure source code in framework-docs is compiled in the build"

This reverts commit c45f8b7.

* Make GeneratorStrategy.generate unreachable on native

This change provides also more information to the user
about the missing generated class when that happens.

Closes spring-projectsgh-29521

* Apply 'instanceof pattern matching' in spring-web

Closes spring-projectsgh-29530

* Polish contribution

See spring-projectsgh-29530

* Apply additional 'instanceof pattern matching' in spring-web

See spring-projectsgh-29530

* Use Set.of() for constant sets where appropriate

* Fix link to Bean Utils Light Library in BeanUtils Javadoc

The URL for the BULL library has changed (not sure when, probably way back).

This updates it to the correct location.

Closes spring-projectsgh-29534

* Make SourceHttpMessageConverter optional

As a follow-up to spring-projectsgh-29277, and since the JAXB support is now
triggered by the classpath presence of a JAXB implementation,
it makes sense to make SourceHttpMessageConverter, previously
configured unconditionally, optional.

That makes a big difference on native (1M of RSS reduction
with current typical Spring Boot 3 arrangement, 3.4M when
other usages of XML are not reachable).

It also brings more consistency between Spring MVC
and Spring WebFlux, and means that XML support for
Spring web applications now needs to be enabled explicitly.

As a consequence, Spring web applications using
javax.xml.transform.Source now needs to configure
SourceHttpMessageConverter explicitly in RestTemplate or
Spring MVC.

Closes spring-projectsgh-29535

* Upgrade to Jackson 2.14.1

Fix an important memory consumption regression, see
FasterXML/jackson-databind#3665
for more details.

Closes spring-projectsgh-29539

* Fix some typos in Kotlin WebClient example code

Closes spring-projectsgh-29538

* Upgrade to Kotlin 1.7.21

Closes spring-projectsgh-29543

* Refine LogAdapter#isPresent

Align LogAdapter#isPresent with ClassUtils#isPresent in order
to catch NoClassDefFoundError and other errors.

Closes spring-projectsgh-29506

* Fix Javadoc link text in BindingResult

Closes spring-projectsgh-29551

* Polishing

* Polish ServletWebRequest and DefaultServerWebExchange

- The return values of ServletWebRequest.validateIfUnmodifiedSince and
  DefaultServerWebExchange.validateIfUnmodifiedSince are not used. So I
  think that it is better to remove the return statements.

- Add missing @nullable declarations to eTag method parameters.

- Simplify if statements

Closes spring-projectsgh-29460

* Polish contribution

See spring-projectsgh-29460

* Apply 'instanceof pattern matching'

* Exclude LocalVariableTableParameterNameDiscoverer based on native image check

See spring-projectsgh-29531

* Apply 'instanceof pattern matching'

* Polishing

* Use AssertJ's hasSize() for collections and maps

Achieved via a global search-and-replace.

* User AssertJ's hasSize() for arrays

Achieved via global search-and-replace.

* Use AssertJ's isEmpty() instead of hasSize(0)

Achieved via global search-and-replace.

* Temporarily re-enable ReactorNetty2StompBrokerRelayIntegrationTests

To see if it still fails on the CI server as it doesn't fail locally
for me, and if it does to get details to investigate.

See spring-projectsgh-29287

* Deprecate LocalVariableTableParameterNameDiscoverer completely

LocalVariableTableParameterNameDiscoverer is not registered by default anymore now.
Java sources should be compiled with `-parameters` instead (available since Java 8).
Also retaining standard Java parameter names for all of Spring's Kotlin sources now.

Closes spring-projectsgh-29531

* Add since attribute to Deprecated annotation

Also retaining standard Java parameter names for Spring's AspectJ sources now.

See spring-projectsgh-29531

* Increase logging for spring-messaging tests

See spring-projectsgh-29287

* Fix javadoc link in AOP extensibility documentation

Closes spring-projectsgh-29554

* Retain default LocalVariableTableParameterNameDiscoverer with warn log entries

For a transition period, LocalVariableTableParameterNameDiscoverer logs a warning for each successful resolution attempt now, suggesting that -parameters was missed.

See spring-projectsgh-29531
See spring-projectsgh-29559

* Next development version (v6.0.2-SNAPSHOT)

* Log connection info in StompBrokerRelayMessageHandler

See spring-projectsgh-29287

* Document removal of CommonsMultipartResolver in MVC setup documentation

Closes spring-projectsgh-29562

* Reduce deprecation warn logging to one entry per introspected class

Closes spring-projectsgh-29563

* Rely on standard parameter name resolution in Bean Validation 3.0

Just configuring additional Kotlin reflection if Kotlin is present.

Closes spring-projectsgh-29566

* ResponseStatusException sets detail from reason again

Closes spring-projectsgh-29567

* Additional documentation notes on Java/Kotlin parameter name retention

See spring-projectsgh-29563

* Next development version (v6.0.3-SNAPSHOT)

* Early support for Jetty 12 (developed against 12.0.0.alpha2)

Reflective getHeaders calls to be revisited; see GitHub issue spring-projects#8938 in Jetty project.
HttpOutput optimization commented out still in order to avoid alpha build dependency.

See spring-projectsgh-29575

* Deprecate JettyWebSocketClient in favor of StandardWebSocketClient

JettyWebSocketClient only supported on Jetty 11, to be phased out.

Closes spring-projectsgh-29576

* Consistent documentation references to Jakarta WebSocket (2.1)

Closes spring-projectsgh-29581

* Reinstate checkstyle for reference docs code snippets

This commit also ensures that checks are performed before the
application is rendered to get early feedback on errors.

* Fix unrendered titles in websocket section

This commit fixes the rendering of titles in the websocket section of
the reference documentation.

Fixes spring-projectsgh-29569

* Split integration chapter in smaller documents

This commit splits the integration chapter of the reference
documentation in smaller documents for easier maintenance.

* Document Observability support in reference docs

Closes spring-projectsgh-29524

* Upgrade to Gradle 7.6

Closes spring-projectsgh-29583

* Upgrade Gradle wrapper

See spring-projectsgh-29583

* Consistently register CGLIB hints for lazy resolution proxy classes

Core JDK/CGLIB proxy registration code extracted to ClassHintUtils.

Closes spring-projectsgh-29584

* Remove erroneous Javadoc link

* Improve logging in TestContextManager

* Forbid loading of test ApplicationContext in AOT mode if AOT processing failed

Prior to this commit, if AOT processing of a test's ApplicationContext
failed, the TestContext Framework (TCF) still attempted to load the
context via standard (JVM) mechanisms when running in AOT mode.

For example, if a test class uses Spring Boot's @MockBean, AOT
processing of that test's context will fail with a WARN log message,
and there will no mapping from that test class to an AOT-generated
ApplicationContextInitializer (ACI). Consequently, when the test suite
is run in AOT mode that particular test class will currently fail with
a confusing stack trace due to the fact that Spring Boot's
SpringApplication attempts to locate a "main" ACI instead of the
missing "test" ACI (missing because it was not generated during AOT
processing).

In general, the TCF should not attempt to load an ApplicationContext in
"JVM mode" while running in "AOT mode".

This commit therefore reworks the logic in
DefaultCacheAwareContextLoaderDelegate to fail fast (with a meaningful
error message) if an AOT-generated ACI cannot be found while running in
AOT mode. This avoids the aforementioned confusion when @MockBean tests
fail in AOT mode (on the JVM or within a native image), and it also
helps to diagnose build problems if AOT processing has not yet been
performed for the project's test suite.

Closes spring-projectsgh-29579

* Polish TestContextManager internals

* Use JUnit Jupiter annotations as examples in TestContextManager JavaDoc

* Update Javadoc regarding JUnit versions

* Add MessageSource getters

See spring-projectsgh-29574

* Polish Testing chapter

* Fix errors in Testing chapter

- group code example callouts to ensure callouts are displayed for the
  correct examples

- add missing callouts

- fix syntax, annotation attribute names, etc.

* Fix typo in observability documentation

Closes spring-projectsgh-29590

* Add title to SockJS iFrames for accessibility compliance

Closes spring-projectsgh-29594

* Polish contribution

See spring-projectsgh-29594

* Polishing

* Fix broken tests in SockJsServiceTests

See spring-projectsgh-29594

* Avoid deprecation warnings in tests

* Rename to AbstractReactiveWebSocketIntegrationTests to avoid duplicate class names

* Polishing

* Polishing

* Add "missing" callout for parity

* Fix code example callouts in reference manual

* Add missing callout

* Apply project formatting rules for ternary operator

Discovered via RegEx: ^\s+\?

* Apply "instanceof pattern matching"

* Introduce update_copyright_headers.sh shell script

In order to automate maintenance of copyright headers in our source
code (especially when merging PRs from external contributors), this
commit introduces an update_copyright_headers.sh script (tested on
mac OS) that will update the copyright headers of all Java, Kotlin,
and Groovy source files that have been added or modified this year
(or at least as far back as the git log history supports it).

For example, running this script currently outputs the following.

Updating copyright headers in Java, Kotlin, and Groovy source code for year 2022
warning: log for 'main' only goes back to Tue, 16 Aug 2022 16:24:55 +0200

* Update copyright headers for source code changed since August 2022

The changes in this commit were performed using the newly introduced
update_copyright_headers.sh script.

* Update Javadoc for MBeanTestUtils

* Apply update_copyright_headers.sh to staged files as well

* Avoid unnecessary parameter name inspection for constructor-arg resolution

Closes spring-projectsgh-29612

* Add equals/hashCode methods to ProblemDetail

Closes spring-projectsgh-29606

* Polishing

* Polish

Closes spring-projectsgh-29619

* Use resolved factory method return type for supplier code generation

Closes spring-projectsgh-29598

* Polishing

* Revised support for Jetty 12 (tested against 12.0.0.alpha2)

Avoids HttpFields optimization completely, relying on Servlet header access instead.
ServletServerHttpResponse provides applyHeaders/adaptHeaders split for better reuse.

See spring-projectsgh-29575

* ResponseStatusException delegates to protected constructor

This ensures that by default the reason is used to set the "detail"
field. It's a follow-up fix to a27f2e9
which resolved the issue partially.

Closes spring-projectsgh-29608

* Deprecate GraphQL media type in favor of new one

This commit deprecates the `"application/graphql+json"` media type in
favor of the new `"application/graphql-response+json"`, since the former
has been removed in graphql/graphql-over-http#215.

Closes spring-projectsgh-29617

* Fix URI override for HttpExchange

Closes spring-projectsgh-29624

* Upgrade to Apache HttpClient 5.2

Includes JRuby 9.4, Groovy 4.0.6, Hibernate ORM 5.6.14, HSQLDB 2.7.1, SLF4J 2.0.5, Caffeine 3.1.2, Gson 2.10, POI 5.2.3, Protobuf 3.21.10, WebJars Locator 0.52, HtmlUnit 2.67, Mockito 4.9, Checkstyle 10.5

Closes spring-projectsgh-29627

* Fix ErrorResponse#type documentation

Closes spring-projectsgh-29632

* Apply "instanceof pattern matching"

* Polish Javadoc for ErrorResponse etc.

* Reinstate test for JmxUtils.locateMBeanServer()

* Update copyright headers

* Polish overview for consistency

* Do not refer to HTML ref docs from HTML ref docs

* Revise PDF ref docs to include TOC, authors, and legal sections

* Polish ref docs build

* Upgrade JMH build plugins

This commit upgrades the Gradle JMH plugin to 0.6.8 and the companion
JMH version to 1.36.

* Reduce heap memory usage in ConcurrentLruCache

Prior to this commit, the `ConcurrentLruCache` implementation would use
arrays of `AtomicReference` as operation buffers, and the buffer count
would be calculated with the nearest power of two for the CPU count.

This can result in significant heap memory usage as each
`AtomicReference` buffer entry adds to the memory pressure. As seen in
FasterXML/jackson-databind#3665, this can add a significant overhead for
no real added benefit for the current use case.

This commit changes the current implementation to use
`AtomicReferenceArray` as buffers and reduce the number of buffers.
JMH benchmarks results are within the error margin so we can assume that
this does not change the performance characteristics for the typical use
case in Spring Framework.

Fixes spring-projectsgh-29520

* Improve invalid Content-Type handling in WebFlux

Closes spring-projectsgh-29565

* Simplify form data handling in HttpRequestValues

Closes spring-projectsgh-29615

* Improve Netty code sample

See spring-projectsgh-29622

* Polishing contribution

Closes spring-projectsgh-29622

* Fix canWrite of PartHttpMessageWriter

See spring-projectsgh-29631

* Push canWrite down into MultipartHttpMessageWriter

The implementation in the base class only matches the
MultipartHttpMessageWriter subclass. The other two override it anyway.

Closes spring-projectsgh-29631

* Polishing, suppression of deprecation warnings, copyright headers, etc.

* Enable backport bot for pull requests

* Correct event name in backport bot config

* Add write permission in backport bot config

* Correct permissions key in backport bot config

* Correct (again) permissions key in backport bot config

* Fall back to JdkClientHttpConnector as ClientHttpConnector

* Fix issue with getHeaders in NoHandlerFoundException

Closes spring-projectsgh-29626

* Add convenience methods for binding error messages

Closes spring-projectsgh-29574

* Apply "instanceof pattern matching" in spring-webflux

Closes spring-projectsgh-29635

* Polishing

* Rename MultipartWebClientIntegrationTests classes to avoid duplicate names

* Polishing

* Reintroduce component index support for Jakarta annotations

Spring Framework 6.0 GA introduced a regression in the component index
support for Jakarta annotations such as @nAmed and @ManagedBean.

Prior to this commit, @nAmed and @ManagedBean components were
registered in the component index at build time; however, component
scanning failed to find those component at run time.

This commit updates ClassPathScanningCandidateComponentProvider so that
`jakarta.*` annotation types are once again supported for component
scanning via the component index at run time.

Closes spring-projectsgh-29641

* Polish var-args declarations

Closes spring-projectsgh-29640

* Fix InputStream violation in DataBufferInputStream

This commit fixes an issue in DataBufferInputStream::mark, which before
did not follow the contract defined by InputStream.

Closes spring-projectsgh-29642

* Fix BindingReflectionHintsRegistrar anonymous classes support

This commit ensures that giving an anonymous class for reflection hints
registration does not result in a NullPointerException, since the
canonical name of anonymous classes is null.

Fixes spring-projectsgh-29657

* Update copyright headers

* Improve Javadoc for SqlLobValue

* Introduce @suite classes for individual modules

* Polishing

* Fix SpEL support for quotes within String literals

Prior to this commit, there were two bugs in the support for quotes
within String literals in SpEL expressions.

- Two double quotes ("") or two single quotes ('') were always replaced
  with one double quote or one single quote, respectively, regardless
  of which quote character was used to enclose the original String
  literal. This resulted in the loss of one of the double quotes when
  the String literal was enclosed in single quotes, and vice versa. For
  example, 'x "" y' became 'x " y'.

- A single quote which was properly escaped in a String literal
  enclosed within single quotes was not escaped in the AST string
  representation of the expression. For example, 'x '' y' became 'x ' y'.

This commit fixes both of these related issues in StringLiteral and
overhauls the structure of ParsingTests.

Closes spring-projectsgh-29604, spring-projectsgh-28356

* Apply 'instanceof pattern matching' in spring-jdbc

* Apply 'instanceof pattern matching' in spring-expression

* Polishing

* Support arrays in AST string representations of SpEL expressions

Prior to this commit, SpEL's ConstructorReference did not provide
support for arrays when generating a string representation of the
internal AST. For example, 'new String[3]' was represented as 'new
String()' instead of 'new String[3]'.

This commit introduces support for standard array construction and array
construction with initializers in ConstructorReference's toStringAST()
implementation.

Closes spring-projectsgh-29665

* Polishing

- primarily automated "clean up" using Eclipse IDE

* Polish CGLIB fork

- primarily automated "clean up" using Eclipse IDE

* Remove top-level permissions from backport-bot.yml

* Optimize object creation PartialMatchHelper

See spring-projectsgh-29634

* Polishing contribution

Closes spring-projectsgh-29634

* Restore top-level read permission for backport bot

* Apply 'instanceof pattern matching' in spring-test and Servlet mocks

* Polish tests in spring-test

* Use URI#create instead of URI constructor where feasible in spring-test

* Use URI#create instead of URI constructor where feasible in spring-web

* Use URI#create instead of URI constructor where feasible in spring-webflux

* Use URI#create instead of URI constructor where feasible in spring-webmvc

* Use URI#create instead of URI constructor where feasible in spring-websocket

* Introduce additional constructors in MockClientHttp[Request|Response]

This commit introduces additional constructors in MockClientHttpRequest
and MockClientHttpResponse that were previously only present in the
internal "test fixtures" in spring-web.

This commit also aligns the mocks in spring-test with the test fixtures
in spring-web to simplify continued maintenance of the mocks and test
fixtures.

Closes spring-projectsgh-29670

* Remove dead code in MockClientHttpRequest

* Support properties on records in BindingReflectionHintsRegistrar

Closes spring-projectsgh-29571

* Refine BindingReflectionHintsRegistrar Kotlin support

Closes spring-projectsgh-29593

* Make @ModelAttribute and @InitBinder reflective

Closes spring-projectsgh-29572

* Upgrade to Micrometer 1.10.2

Closes spring-projectsgh-29678

* Start building against Reactor 2022.0.1

See spring-projectsgh-29679

* Upgrade optional dependencies

* Use consistent visibility for ResponseEntityExceptionHandler.getMessageSource()

See spring-projectsgh-29574
Closes spring-projectsgh-29676

* Clean up Javadoc and source code regarding " ." typos

* Align multipart codecs on client and server

This commit ensures that the same multipart codecs are registered on
both client and server. Previously, only the client enabled only sending
 multipart, and the server only receiving.

Closes spring-projectsgh-29630

* Detect SQL state 23505/40001 as DuplicateKeyException/CannotAcquireLockException

Favors PessimisticLockingFailureException over plain ConcurrencyFailureException.
Deprecates CannotSerializeTransactionException and DeadlockLoserDataAccessException.

Closes spring-projectsgh-29511
Closes spring-projectsgh-29675

* Avoid NPE on BeanDescriptor access with SimpleBeanInfoFactory

Closes spring-projectsgh-29681

* Polishing

* Polish Javadoc

* Update copyright date

* Add missing Javadoc

See spring-projectsgh-29574

* Revise RepeatableContainersTests

* Support repeatable annotation containers with multiple attributes

Prior to this commit, there was a bug in the implementation of
StandardRepeatableContainers.computeRepeatedAnnotationsMethod() which
has existed since Spring Framework 5.2 (when
StandardRepeatableContainers was introduced). Specifically,
StandardRepeatableContainers ignored any repeatable container
annotation if it declared attributes other than `value()`. However,
Java permits any number of attributes in a repeatable container
annotation.

In addition, the changes made in conjunction with spring-projectsgh-20279 made the bug
in StandardRepeatableContainers apparent when using the
getMergedRepeatableAnnotations() or findMergedRepeatableAnnotations()
method in AnnotatedElementUtils, resulting in regressions for the
behavior of those two methods.

This commit fixes the regressions and bug by altering the logic in
StandardRepeatableContainers.computeRepeatedAnnotationsMethod() so that
it explicitly looks for the `value()` method and ignores any other
methods declared in a repeatable container annotation candidate.

Closes spring-projectsgh-29685

* Remove obsolete AttributeMethods.hasOnlyValueAttribute() method

See spring-projectsgh-29685

* Upgrade to Reactor 2022.0.1

Closes spring-projectsgh-29679

* Support non-standard HTTP methods in FrameworkServlet

This commit ensures that HTTP methods not supported by HttpServlet, for
instance WebDAV methods, are still supported in FrameworkServlet.

Closes spring-projectsgh-29689

* Remove duplicated test code

* Improve Javadoc for RepeatableContainers

* Next development version (v6.0.4-SNAPSHOT)

* Fix manipulating property sources example in Javadoc for ConfigurableEnvironment

The "manipulating property sources" example in the Javadoc for
`ConfigurableEnvironment` states that `MutablePropertySources`
expect a `Map<String,String>`; whereas it expects a
`Map<String,Object>`.

Closes spring-projectsgh-29693

* Polishing

* Polishing

* Improve documentation for literals in SpEL expressions

Closes spring-projectsgh-29700

* Extract ResourceEntityResolver HTTPS schema resolution fallback

This commit extracts the DTD/XSD remote lookup fallback from the
resolveEntity() method into a protected method.

A WARN-level logging statement is added to the extracted fallback in
order to make it clear that remote lookup happened.

Overriding the protected method would allow users to avoid this
fallback entirely if it isn't desirable, without the need to duplicate
the local resolution code.

Closes spring-projectsgh-29697

* Polish contribution

See spring-projectsgh-29697

* Fix typos in reference manual

Closes spring-projectsgh-29694

* Fix link to Jakarta Mail

Closes spring-projectsgh-29694

* Remove ref to JOTM, inactive since 2009

Closes spring-projectsgh-29694

* Remove statement that users could be on Java < 5

Closes spring-projectsgh-29694

* Rework linking to Spring MVC Async support vs WebFlux section

The link was previously named "Compared to WebFlux", which is easy to
mix up with the various links to equivalent sections in the WebFlux
chapter. Here the links point to a small section comparing the Servlet
Async API to the WebFlux stack from a high perspective.

In this commit we eliminate most of these links, except at the
beginning of the Asynchronous section. We also add a small mention of
the Servlet configuration in the comparison paragraphs, since the
Configuring section is the one furthest from the comparison paragraphs
that used to have a link to it.

Closes spring-projectsgh-29694

* Fix subsection style in WebFlux Concurrency Model

The block title style previously used was not rendered in HTML and the
title couldn't be differentiated from the text. Though, it was in the
PDF, as italics.

Introducing delimited blocks in the open (`--`) style did introduce
styling, but the vertical alignment isn't great.

This commit turns these block titles to actual (deep) section titles.
In the final HTML, at this depth there is no numbering but bold styling
is there. The PDF rendering has also been verified to have relevant
style.

Closes spring-projectsgh-29694

* Change plain 'WebFlux' links to 'See equivalent in the Reactive stack'

Closes spring-projectsgh-29694

* Change plain 'WebMVC' links to 'See equivalent in the Servlet stack'

Closes spring-projectsgh-29694

* Cross reference WebTestClient section

* Update Jakarta Mail info in ref docs

Closes spring-projectsgh-29707

* Remove duplicate words in reference manual

Found using regular expression: \b(\w+)\s+\1\b

* Remove duplicated words in Javadoc

* Fix typos in reference manual

* Fix formatting in examples

* Fix typos in anchors

* Polishing

* Update copyright headers

* Apply "instanceof pattern matching" (spring-projects#29710)

* Polishing

* Update Trigger & TriggerContext reference documentation

Closes spring-projectsgh-29702

* Revert incorrect change to ParamAware Javadoc

* Apply "instanceof pattern matching" in spring-aop

* Fix path within mapping when pattern contains ".*"

Prior to this commit, extracting the path within handler mapping would
result in "" if the matching path element would be a Regex and contain
".*". This could cause issues with resource handling if the handler
mapping pattern was similar to `"/folder/file.*.extension"`.

This commit introduces a new `isLiteral()` method in the `PathElement`
abstract class that expresses whether the path element can be compared
as a String for path matching or if it requires a more elaborate
matching process.

Using this method for extracting the path within handler mapping avoids
relying on wildcard count or other properties.

Fixes spring-projectsgh-29712

* Apply update_copyright_headers.sh

Co-authored-by: Juergen Hoeller <hoellerj@vmware.com>
Co-authored-by: Sam Brannen <sam@sambrannen.com>
Co-authored-by: Andriy <ophiuhus@ukr.net>
Co-authored-by: Stephane Nicoll <snicoll@vmware.com>
Co-authored-by: Andy Wilkinson <wilkinsona@vmware.com>
Co-authored-by: Arjen Poutsma <poutsmaa@vmware.com>
Co-authored-by: Spring Builds <spring-builds@users.noreply.github.com>
Co-authored-by: Brian Clozel <bclozel@vmware.com>
Co-authored-by: Sébastien Deleuze <sdeleuze@vmware.com>
Co-authored-by: wizard <925553434@qq.com>
Co-authored-by: divcon <sungjinpark.08@gmail.com>
Co-authored-by: David Costanzo <david_costanzo@yahoo.com>
Co-authored-by: Marten Deinum <mdeinum@gmail.com>
Co-authored-by: André Gasser <andre.gasser@protonmail.com>
Co-authored-by: jiangying <krivergo3@gmail.com>
Co-authored-by: rstoyanchev <rstoyanchev@vmware.com>
Co-authored-by: Yanming Zhou <zhouyanming@gmail.com>
Co-authored-by: Aashay Chapatwala <49100046+Aashay-Chapatwala@users.noreply.github.com>
Co-authored-by: Johnny Lim <izeye@naver.com>
Co-authored-by: Baljit Singh <baljit.singh@verizon.com>
Co-authored-by: Spark61 <ytspark61@gmail.com>
Co-authored-by: CoderYellow <Pf19890604@>
Co-authored-by: Moritz Halbritter <mkammerer@vmware.com>
Co-authored-by: divcon <sungjin.park08@gmail.com>
Co-authored-by: Sam Brannen <sbrannen@vmware.com>
Co-authored-by: ShenFeng312 <49786112+ShenFeng312@users.noreply.github.com>
Co-authored-by: koo.taejin <koo.taejin@toss.im>
Co-authored-by: Carlos Belizón <carlos.belizon.ibanez@gmail.com>
Co-authored-by: Simon Baslé <sbasle@vmware.com>
Co-authored-by: diguage <leejun119@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants