Various memory leak fixes

This commit is contained in:
samczsun 2016-10-01 18:24:48 -04:00 committed by Shaun Bennett
parent b3ed9db2c7
commit a338fb27d3

View File

@ -1,20 +1,32 @@
package mineplex.core.memory; package mineplex.core.memory;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Set;
import mineplex.core.MiniPlugin; import mineplex.core.MiniPlugin;
import mineplex.core.updater.UpdateType; import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent; import mineplex.core.updater.event.UpdateEvent;
import net.minecraft.server.v1_8_R3.CraftingManager; import net.minecraft.server.v1_8_R3.CraftingManager;
import net.minecraft.server.v1_8_R3.Enchantment;
import net.minecraft.server.v1_8_R3.EnchantmentManager;
import net.minecraft.server.v1_8_R3.IInventory; import net.minecraft.server.v1_8_R3.IInventory;
import net.minecraft.server.v1_8_R3.WorldServer;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.HumanEntity; import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityDamageByBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
public class MemoryFix extends MiniPlugin public class MemoryFix extends MiniPlugin
@ -28,6 +40,151 @@ public class MemoryFix extends MiniPlugin
//_intHashMap = IntHashMap.class. //_intHashMap = IntHashMap.class.
} }
@EventHandler
public void fixLastDamageEventLeaks(UpdateEvent event)
{
if (event.getType() != UpdateType.SLOW)
return;
List<World> worldList = Bukkit.getWorlds();
Set<World> worlds = new HashSet<>(worldList);
// Sanity check
if (worlds.size() != worldList.size())
throw new RuntimeException("Error: Duplicated worlds?!?!");
for (World world : worlds)
{
WorldServer worldServer = ((CraftWorld) world).getHandle();
for (net.minecraft.server.v1_8_R3.Entity nmsentity : worldServer.entityList)
{
Entity entity = nmsentity.getBukkitEntity();
EntityDamageEvent lastDamageCause = entity.getLastDamageCause();
if (lastDamageCause != null)
{
Entity damaged = lastDamageCause.getEntity();
Entity damagerEntity = null;
Block damagerBlock = null;
if (lastDamageCause instanceof EntityDamageByEntityEvent)
damagerEntity = ((EntityDamageByEntityEvent) lastDamageCause).getDamager();
if (lastDamageCause instanceof EntityDamageByBlockEvent)
damagerBlock = ((EntityDamageByBlockEvent) lastDamageCause).getDamager();
boolean shouldRemove = false;
if (!damaged.isValid())
shouldRemove = true;
else if (damagerEntity != null)
{
if (!damagerEntity.isValid())
shouldRemove = true;
else if (!worlds.contains(damagerEntity.getWorld()))
shouldRemove = true;
}
else if (damagerBlock != null)
{
if (!worlds.contains(damagerBlock.getWorld()))
shouldRemove = true;
}
if (shouldRemove)
entity.setLastDamageCause(null);
}
}
}
}
private static Object ENCHANTMENTMANAGER_D;
private static Field ENCHANTMENT_MODIFIER_THORNS_A;
private static Field ENCHANTMENT_MODIFIER_THORNS_B;
private static boolean ENCHANTMENTMANAGER_D_SUCCESFUL;
private static Object ENCHANTMENTMANAGER_E;
private static Field ENCHANTMENT_MODIFIER_ARTHROPODS_A;
private static Field ENCHANTMENT_MODIFIER_ARTHROPODS_B;
private static boolean ENCHANTMENTMANAGER_E_SUCCESFUL;
static
{
try
{
Field field = EnchantmentManager.class.getDeclaredField("d");
field.setAccessible(true);
ENCHANTMENTMANAGER_D = field.get(null);
ENCHANTMENT_MODIFIER_THORNS_A = ENCHANTMENTMANAGER_D.getClass().getDeclaredField("a");
ENCHANTMENT_MODIFIER_THORNS_A.setAccessible(true);
ENCHANTMENT_MODIFIER_THORNS_B = ENCHANTMENTMANAGER_D.getClass().getDeclaredField("b");
ENCHANTMENT_MODIFIER_THORNS_B.setAccessible(true);
ENCHANTMENTMANAGER_D_SUCCESFUL = true;
}
catch (ReflectiveOperationException e)
{
e.printStackTrace();
}
try
{
Field field = EnchantmentManager.class.getDeclaredField("e");
field.setAccessible(true);
ENCHANTMENTMANAGER_E = field.get(null);
ENCHANTMENT_MODIFIER_ARTHROPODS_A = ENCHANTMENTMANAGER_E.getClass().getDeclaredField("a");
ENCHANTMENT_MODIFIER_ARTHROPODS_A.setAccessible(true);
ENCHANTMENT_MODIFIER_ARTHROPODS_B = ENCHANTMENTMANAGER_E.getClass().getDeclaredField("b");
ENCHANTMENT_MODIFIER_ARTHROPODS_B.setAccessible(true);
ENCHANTMENTMANAGER_E_SUCCESFUL = true;
}
catch (ReflectiveOperationException e)
{
e.printStackTrace();
}
}
@EventHandler
public void fixEnchantmentManager(UpdateEvent event)
{
if (event.getType() != UpdateType.SLOW)
return;
if (ENCHANTMENTMANAGER_D_SUCCESFUL)
{
try
{
net.minecraft.server.v1_8_R3.Entity a = (net.minecraft.server.v1_8_R3.Entity) ENCHANTMENT_MODIFIER_THORNS_A.get(ENCHANTMENTMANAGER_D);
net.minecraft.server.v1_8_R3.Entity b = (net.minecraft.server.v1_8_R3.Entity) ENCHANTMENT_MODIFIER_THORNS_B.get(ENCHANTMENTMANAGER_D);
if ((a != null && !a.valid) || (b != null && !b.valid))
{
ENCHANTMENT_MODIFIER_THORNS_A.set(ENCHANTMENTMANAGER_D, null);
ENCHANTMENT_MODIFIER_THORNS_B.set(ENCHANTMENTMANAGER_D, null);
}
}
catch (ReflectiveOperationException e)
{
e.printStackTrace();
}
}
if (ENCHANTMENTMANAGER_E_SUCCESFUL)
{
try
{
net.minecraft.server.v1_8_R3.Entity a = (net.minecraft.server.v1_8_R3.Entity) ENCHANTMENT_MODIFIER_ARTHROPODS_A.get(ENCHANTMENTMANAGER_E);
net.minecraft.server.v1_8_R3.Entity b = (net.minecraft.server.v1_8_R3.Entity) ENCHANTMENT_MODIFIER_ARTHROPODS_B.get(ENCHANTMENTMANAGER_E);
if ((a != null && !a.valid) || (b != null && !b.valid))
{
ENCHANTMENT_MODIFIER_ARTHROPODS_A.set(ENCHANTMENTMANAGER_E, null);
ENCHANTMENT_MODIFIER_ARTHROPODS_B.set(ENCHANTMENTMANAGER_E, null);
}
}
catch (ReflectiveOperationException e)
{
e.printStackTrace();
}
}
}
@EventHandler @EventHandler
public void fixInventoryLeaks(UpdateEvent event) public void fixInventoryLeaks(UpdateEvent event)
{ {