GuiRenderer retains references to item models that have been rendered in GUI after resource pack reloads, creating a memory leak that can lead to crashes. The item model retention is not dependent on the currently applied packs, so loading into strictly vanilla resources does not resolve the leak. This issue has existed since the relevant code was first introduced in 1.21.6.
Steps to Reproduce:
Install spark or otherwise observe the internal state of GuiRenderer
Place a few (for example 6) distinct items on your hotbar
Change GUI scale to ensure clean state
Run
/spark heapsummaryand observe 6net.minecraft.client.gui.render.GuiRenderer$AtlasPositioninstancesReload resources with F3+T (or perform multiple times)
Run
/spark heapsummaryagain and observe 12 instances (doubled or times however many reloads)Change GUI scale again
Run
/spark heapsummaryand observe it returns to 6 instances
Expected Behavior: Resource pack reloads should invalidate the UI item atlas texture, ensuring all previously rendered items are discarded.
Actual Behavior: After resource pack reloads, new model instances with new identities are created. When rendered, these are treated as new items and added to the item atlas texture. The old model identities from before the reload remain in the map, preventing garbage collection of all previous model data.
Workaround: Changing GUI scale forcibly triggers invalidation allowing for garbage collection.
Code Analysis:
The GuiRenderer#atlasPositions map tracks which model identities have been rendered to which positions in the UI item atlas texture. This allows items to be rendered once and reused across frames.
The map and atlas textures are only invalidated via invalidateItemAtlas() in two scenarios:
GUI scale change
Atlas capacity exceeded requiring resize
Meanwhile, resource pack reloads are not handled. When resources reload, all models are recreated with new reference equality identities. The new identities don't match existing atlasPositions entries, so they're added fresh. The old identities remain as keys, holding strong references to all their associated model data (BakedQuad, ItemTransform, SpriteContents, etc.), preventing garbage collection.
Memory Impact: Testing with large resource packs shows dramatic increases:
BakedQuad: 610k → 10.5M instancesVector3f: 290k → 7.5M instancesItemTransform: 27k → 725k instancesSpriteContents: 10k → 163k instancesAtlasPosition: 12 → 168 instances
Spark reports for those numbers: First loaded a large pack, then after a dozen reloads, finally after changing GUI scale.
The leak is particularly severe for resource packs using traditional custom model data/range dispatch patterns, where viewing a single item causes all variant models to be leaked together.
Environment
Java Version: OpenJDK 21.0.7+6-LTS
OS: Windows 10 64-bit
System Memory: 16GB
JVM Memory: 2GB
Comments 0
No comments.