Add utilities that RuntimeEnumExtender expects to exist

This commit is contained in:
tterrag 2019-01-17 13:11:54 -05:00
parent 3b029ba031
commit 0d1a2f2af3
2 changed files with 33 additions and 10 deletions

View file

@ -45,7 +45,7 @@ public class RuntimeEnumExtender implements ILaunchPluginService {
private final Type ENUM = Type.getType(Enum.class);
private final Type ARRAY_UTILS = Type.getType("Lorg/apache/commons/lang3/ArrayUtils;"); //Don't directly reference this to prevent class loading.
private final String ADD_DESC = Type.getMethodDescriptor(Type.getType(Object[].class), Type.getType(Object[].class), Type.getType(Object.class));
private final Type ENUM_HELPER = Type.getType("Lnet/minecraftforge/common/util/EnumHelper;"); //Again, not direct reference to prevent class loading.
private final Type UNSAFE_HACKS = Type.getType("Lnet/minecraftforge/fml/UnsafeHacks;"); //Again, not direct reference to prevent class loading.
private final String CLEAN_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Class.class));
private final String NAME_DESC = Type.getMethodDescriptor(STRING);
private final String EQUALS_DESC = Type.getMethodDescriptor(Type.BOOLEAN_TYPE, STRING);
@ -181,7 +181,7 @@ public class RuntimeEnumExtender implements ILaunchPluginService {
ins.putstatic(classType.getInternalName(), values.name, values.desc);
//EnumHelper.cleanEnumCache(ThisType.class)
ins.visitLdcInsn(classType);
ins.invokestatic(ENUM_HELPER.getInternalName(), "cleanEnumCache", CLEAN_DESC, false);
ins.invokestatic(UNSAFE_HACKS.getInternalName(), "cleanEnumCache", CLEAN_DESC, false);
//return ret
ins.load(vars, classType);
ins.areturn(classType);

View file

@ -19,14 +19,17 @@
package net.minecraftforge.fml;
import java.lang.reflect.Field;
import java.util.Optional;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
@SuppressWarnings("restriction")
public class UnsafeHacks
{
private static final Unsafe UNSAFE;
static {
static
{
try
{
final Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
@ -40,11 +43,11 @@ public class UnsafeHacks
}
@SuppressWarnings("unchecked")
public static <T> T newInstance(Class<T> packetClass)
public static <T> T newInstance(Class<T> clazz)
{
try
{
return (T) UNSAFE.allocateInstance(packetClass);
return (T) UNSAFE.allocateInstance(clazz);
}
catch (InstantiationException e)
{
@ -53,15 +56,16 @@ public class UnsafeHacks
}
@SuppressWarnings("unchecked")
public static <T> T getField(Field field, Object object) {
public static <T> T getField(Field field, Object object)
{
final long l = UNSAFE.objectFieldOffset(field);
return (T) UNSAFE.getObject(object, l);
}
public static void setField(Field data, Object object, Object buffer)
public static void setField(Field data, Object object, Object value)
{
long offset = UNSAFE.objectFieldOffset(data);
UNSAFE.putObject(object, offset, buffer);
UNSAFE.putObject(object, offset, value);
}
public static int getIntField(Field f, Object obj)
@ -75,4 +79,23 @@ public class UnsafeHacks
long offset = UNSAFE.objectFieldOffset(data);
UNSAFE.putInt(object, offset, value);
}
// Make sure we don't crash if any future versions change field names
private static Optional<Field> findField(Class<?> clazz, String name)
{
for (Field f : clazz.getDeclaredFields())
{
if (f.getName().equals(name))
{
return Optional.of(f);
}
}
return Optional.empty();
}
public static void cleanEnumCache(Class<? extends Enum<?>> enumClass) throws Exception
{
findField(Class.class, "enumConstantDirectory").ifPresent(f -> setField(f, enumClass, null));
findField(Class.class, "enumConstants").ifPresent(f -> setField(f, enumClass, null));
}
}