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
1 changed files with 169 additions and 12 deletions

View File

@ -1,52 +1,209 @@
package mineplex.core.memory;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import mineplex.core.MiniPlugin;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
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.WorldServer;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
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;
public class MemoryFix extends MiniPlugin
{
private static Field _intHashMap;
public MemoryFix(JavaPlugin plugin)
{
super("Memory Fix", plugin);
//_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
public void fixInventoryLeaks(UpdateEvent event)
{
if (event.getType() != UpdateType.SLOW)
return;
for (World world : Bukkit.getWorlds())
{
for (Object tileEntity : ((CraftWorld)world).getHandle().tileEntityList)
for (Object tileEntity : ((CraftWorld) world).getHandle().tileEntityList)
{
if (tileEntity instanceof IInventory)
{
Iterator<HumanEntity> entityIterator = ((IInventory)tileEntity).getViewers().iterator();
Iterator<HumanEntity> entityIterator = ((IInventory) tileEntity).getViewers().iterator();
while (entityIterator.hasNext())
{
HumanEntity entity = entityIterator.next();
if (entity instanceof CraftPlayer && !((CraftPlayer)entity).isOnline())
if (entity instanceof CraftPlayer && !((CraftPlayer) entity).isOnline())
{
entityIterator.remove();
}
@ -54,17 +211,17 @@ public class MemoryFix extends MiniPlugin
}
}
}
CraftingManager.getInstance().lastCraftView = null;
CraftingManager.getInstance().lastRecipe = null;
}
@EventHandler
public void fixEntityTrackerLeak(UpdateEvent event)
{
if (event.getType() != UpdateType.SLOW)
return;
// NEED TO FIX STUCK NETWORKMANAGERS.....
/*
for (World world : Bukkit.getWorlds())