Skip to content

Instantly share code, notes, and snippets.

@avafloww
Last active July 24, 2020 05:18
Show Gist options
  • Save avafloww/6e0e36be6c95632d7a85 to your computer and use it in GitHub Desktop.
Save avafloww/6e0e36be6c95632d7a85 to your computer and use it in GitHub Desktop.
Entity metadata memory leak test plugin
package com.forairan.metatest;
import java.lang.reflect.Field;
import java.util.Map;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.craftbukkit.v1_7_R3.CraftServer;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Horse;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataStoreBase;
import org.bukkit.plugin.java.JavaPlugin;
public class MetaTestPlugin extends JavaPlugin implements Listener {
@Override
public void onEnable() {
getServer().getPluginManager().registerEvents(this, this);
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (label.equalsIgnoreCase("metatest")) {
if (sender instanceof Player) {
Player p = (Player) sender;
if (args.length < 1) {
sender.sendMessage("Usage: /metatest <number of entities>");
return false;
} else {
int number = 10;
try {
number = Integer.parseInt(args[0]);
} catch (NumberFormatException nfe) {
sender.sendMessage("Invalid number; defaulting to 10.");
}
for (int i = 0; i < number; i++) {
final Horse horse = (Horse) p.getWorld().spawnEntity(p.getLocation(), EntityType.HORSE);
horse.setMetadata("bigData", new FixedMetadataValue(this, new ReallyBigObject()));
horse.remove();
}
sender.sendMessage("Spawned " + number + " horses, added metadata, and removed.");
sendMetadataStoreInfo(sender);
return true;
}
} else {
sender.sendMessage("Please execute this command ingame.");
return false;
}
} else if (label.equalsIgnoreCase("gc")) {
System.gc();
sender.sendMessage("System.gc() executed.");
return true;
} else if (label.equalsIgnoreCase("checkmeta")) {
sendMetadataStoreInfo(sender);
return true;
}
return false;
}
private void sendMetadataStoreInfo(CommandSender sender) {
// Get the entity map via reflection magic
CraftServer craftServer = (CraftServer) getServer();
Map metadataMap;
try {
Field f = MetadataStoreBase.class.getDeclaredField("metadataMap");
f.setAccessible(true);
metadataMap = (Map) f.get(craftServer.getEntityMetadata());
} catch (ReflectiveOperationException ex) {
sender.sendMessage("Error while reflecting: " + ex.getMessage());
sender.sendMessage("See console for details.");
ex.printStackTrace();
return;
}
// Spit it out
sender.sendMessage("Objects in entity metadata store: " + metadataMap.size());
}
private static class ReallyBigObject {
private final byte[] data = new byte[16384];
}
}
name: EntityMetadataTest
version: 1
author: Forairan
main: com.forairan.metatest.MetaTestPlugin
commands:
metatest:
description: Tests the entity metadata store bug.
gc:
description: Runs System.gc().
checkmeta:
description: Checks the metadata store.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment