softvisionfd opened a new pull request, #1359:
URL: https://github.com/apache/poi/pull/1359

   `CellFormat.getInstance(Locale, String)` caches parsed formats in 
`WeakHashMap<Locale, WeakHashMap<String, CellFormat>>`. The cached `CellFormat` 
holds its own format string (`this.format`), i.e. the value strongly references 
the weak key, so no entry is ever released (the case the `WeakHashMap` javadoc 
warns about). `DataFormatter` routes every multi-section or conditional number 
format through this cache, so each distinct format string of every workbook 
formatted stays in memory for the life of the JVM: 20,000 distinct 
three-section formats retain 45 MB (JDK 21). A service converting untrusted 
workbooks accumulates this without bound.
   
   The change holds the cached `CellFormat` through a `WeakReference`, so an 
entry is released together with its key once nothing else refers to the 
`CellFormat`. `DataFormatter` does not keep it ("non-cacheable - CellFormat 
does that"), so in practice an entry now lasts until the next garbage 
collection; `getInstance` already documents that two calls "may or may not 
return the same object". Measured: retained heap back at the level of a run 
without multi-section formats (8.4 vs. 7.9 MB), and steady formatting 
throughput unchanged despite the shorter-lived entries (2.34 vs. 2.36 s per 1M 
calls).
   
   Alternatives considered: `SoftReference` (keeps entries until memory 
pressure, harder to test) or a bounded LRU (deterministic, but needs a size 
limit). Happy to switch if maintainers prefer either.
   
   Test: `TestCellFormat#testCacheReleasesUnusedFormats` — fails on trunk, 
passes with the change. It relies on `System.gc()` and is not reliable under 
`-XX:+DisableExplicitGC`.
   
   Tested: the change was compiled against trunk and measured with the patched 
class on 5.5.1; the logic of the new test fails without and passes with the 
change. I did not run the full Gradle build locally.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to