Skip to content

CoreProtect 24.0 triggers CraftLegacy initialization and huge temporary memory allocations when logging CraftEngine custom blocks #957

Description

@dimamik3-prog

CoreProtect version:
24.0 Community Edition

Server:
Purpur 26.1.2-2592

Java:
25

Related plugin:
CraftEngine 26.7.4

Description:
CoreProtect 24.0 triggers Bukkit CraftLegacy initialization when it logs the first persisted CraftEngine custom block broken after a server restart.

This causes a very large one-time memory allocation burst.

The issue is reproducible with different CraftEngine custom blocks/furniture, for example:

  • sofa
  • safe block

It is not specific to one custom block type.

Steps to reproduce:

  1. Install CoreProtect 24.0 and CraftEngine 26.7.4.
  2. Place any CraftEngine custom block/furniture.
  3. Restart the server.
  4. Break the previously placed CraftEngine object.
  5. Observe the console and memory usage.

Expected behavior:
CoreProtect should log the custom block normally without initializing Bukkit legacy material support.

Actual behavior:
On the first break of a persisted CraftEngine object after each restart, the following warning appears:

[org.bukkit.craftbukkit.legacy.CraftLegacy] Initializing Legacy Material Support. Unless you have legacy plugins and/or data this is a bug!

With debug=true, Bukkit prints this stack trace:

java.lang.Exception
at org.bukkit.craftbukkit.legacy.CraftLegacy.(CraftLegacy.java:266)
at org.bukkit.craftbukkit.util.CraftMagicNumbers.fromLegacy(CraftMagicNumbers.java:234)
at org.bukkit.Material.getMaterial(Material.java:3047)
at CoreProtect-CE-24.0.jar//net.coreprotect.utility.MaterialUtils.getType(MaterialUtils.java:138)
at CoreProtect-CE-24.0.jar//net.coreprotect.utility.BlockUtils.stringToByteData(BlockUtils.java:36)
at CoreProtect-CE-24.0.jar//net.coreprotect.database.statement.BlockStatement.insert(BlockStatement.java:18)
at CoreProtect-CE-24.0.jar//net.coreprotect.database.logger.BlockBreakLogger.log(BlockBreakLogger.java:91)
at CoreProtect-CE-24.0.jar//net.coreprotect.consumer.process.BlockBreakProcess.process(BlockBreakProcess.java:25)
at CoreProtect-CE-24.0.jar//net.coreprotect.consumer.process.Process.processConsumer(Process.java:148)
at CoreProtect-CE-24.0.jar//net.coreprotect.consumer.Consumer.run(Consumer.java:134)
at java.base/java.lang.Thread.run(Thread.java:1474)

Immediately afterwards, G1GC reports multiple very large temporary Eden allocations, for example:

1.0 GB freed from G1 Eden Space
1.0 GB -> 0 bytes

1.1 GB freed from G1 Eden Space
1.1 GB -> 0 bytes

1.2 GB freed from G1 Eden Space
1.2 GB -> 0 bytes

This happens several times within a few seconds.

Important behavior:

  • Newly placed CraftEngine blocks do not trigger this before a restart.
  • The first persisted CraftEngine block broken after restart triggers it.
  • Further CraftEngine block breaks during the same server session do not trigger the same spike.
  • After another restart, the issue can be reproduced again.
  • This does not appear to be a traditional heap leak; most temporary memory is reclaimed by G1GC.
  • The process/container memory can still increase significantly because CraftLegacy initialization causes very large allocations.

Root cause:
The stack trace shows CoreProtect calling:

net.coreprotect.utility.MaterialUtils.getType()

which eventually reaches:

Material.getMaterial(name, true)

The legacy=true fallback causes Bukkit to call CraftMagicNumbers.fromLegacy(), which initializes CraftLegacy.

CraftEngine custom block IDs are not normal Bukkit Material values, so this fallback is reached when CoreProtect tries to resolve them.

Tested fix:
I patched CoreProtect 24.0 so that the legacy material lookup is no longer used for this fallback.

After the patch:

  • CraftLegacy is no longer initialized when breaking persisted CraftEngine blocks.
  • The large allocation burst disappears.
  • CoreProtect still logs CraftEngine custom blocks correctly.

CoreProtect lookup still shows entries such as:

  • player placed craftengine:custom_31
  • player broke craftengine:custom_31

So the custom block logging functionality continues to work.

Suggested fix:
Avoid calling Material.getMaterial(name, true) for unknown/custom material identifiers.

A modern/non-legacy lookup or a separate handling path for custom block IDs would prevent CraftLegacy from being initialized.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions