Clear ObjectHolder Throwable fields after registry events fire

This commit is contained in:
embeddedt 2023-04-16 11:39:54 -04:00
parent 61af88a2ab
commit f36a8f4266
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
2 changed files with 49 additions and 1 deletions

View File

@ -18,6 +18,7 @@ import org.apache.logging.log4j.Logger;
import org.embeddedt.modernfix.core.config.ModernFixConfig;
import org.embeddedt.modernfix.entity.EntityDataIDSyncHandler;
import org.embeddedt.modernfix.packet.PacketHandler;
import org.embeddedt.modernfix.registry.ObjectHolderClearer;
import org.embeddedt.modernfix.structure.AsyncLocator;
import org.embeddedt.modernfix.util.KubeUtil;
@ -91,7 +92,7 @@ public class ModernFix {
ModLoader.get().addWarning(new ModLoadingWarning(ModLoadingContext.get().getActiveContainer().getModInfo(), ModLoadingStage.COMMON_SETUP, "modernfix.no_lazydfu"));
});
}
ObjectHolderClearer.clearThrowables();
}
@SubscribeEvent

View File

@ -0,0 +1,47 @@
package org.embeddedt.modernfix.registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
import net.minecraftforge.registries.ObjectHolderRegistry;
import org.embeddedt.modernfix.ModernFix;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
public class ObjectHolderClearer {
/**
* Many of the built-in Forge holders needlessly hold on to an exception.
*/
public static void clearThrowables() {
Set<Consumer<Predicate<ResourceLocation>>> holders = ObfuscationReflectionHelper.getPrivateValue(ObjectHolderRegistry.class, null, "objectHolders");
if(holders != null) {
int numCleared = 0;
HashMap<Class<?>, Field> throwableField = new HashMap<>();
Throwable singletonThrowable = new Throwable("[This stacktrace was cleared to save memory]");
try {
for(Consumer<Predicate<ResourceLocation>> holder : holders) {
Field target = throwableField.computeIfAbsent(holder.getClass(), clz -> {
Field[] clzFields = clz.getDeclaredFields();
for(Field f : clzFields) {
if(Throwable.class.isAssignableFrom(f.getType())) {
f.setAccessible(true);
return f;
}
}
return null;
});
if(target != null) {
target.set(holder, singletonThrowable);
numCleared++;
}
}
} catch(RuntimeException | ReflectiveOperationException | NoClassDefFoundError ignored) {
}
ModernFix.LOGGER.debug("Cleared " + numCleared + " object holder stacktrace references");
}
}
}