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 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 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 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 CLEAN_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Class.class));
private final String NAME_DESC = Type.getMethodDescriptor(STRING); private final String NAME_DESC = Type.getMethodDescriptor(STRING);
private final String EQUALS_DESC = Type.getMethodDescriptor(Type.BOOLEAN_TYPE, 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); ins.putstatic(classType.getInternalName(), values.name, values.desc);
//EnumHelper.cleanEnumCache(ThisType.class) //EnumHelper.cleanEnumCache(ThisType.class)
ins.visitLdcInsn(classType); ins.visitLdcInsn(classType);
ins.invokestatic(ENUM_HELPER.getInternalName(), "cleanEnumCache", CLEAN_DESC, false); ins.invokestatic(UNSAFE_HACKS.getInternalName(), "cleanEnumCache", CLEAN_DESC, false);
//return ret //return ret
ins.load(vars, classType); ins.load(vars, classType);
ins.areturn(classType); ins.areturn(classType);

View file

@ -19,14 +19,17 @@
package net.minecraftforge.fml; package net.minecraftforge.fml;
import java.lang.reflect.Field;
import java.util.Optional;
import sun.misc.Unsafe; import sun.misc.Unsafe;
import java.lang.reflect.Field; @SuppressWarnings("restriction")
public class UnsafeHacks public class UnsafeHacks
{ {
private static final Unsafe UNSAFE; private static final Unsafe UNSAFE;
static { static
{
try try
{ {
final Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); final Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
@ -40,11 +43,11 @@ public class UnsafeHacks
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> T newInstance(Class<T> packetClass) public static <T> T newInstance(Class<T> clazz)
{ {
try try
{ {
return (T) UNSAFE.allocateInstance(packetClass); return (T) UNSAFE.allocateInstance(clazz);
} }
catch (InstantiationException e) catch (InstantiationException e)
{ {
@ -53,15 +56,16 @@ public class UnsafeHacks
} }
@SuppressWarnings("unchecked") @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); final long l = UNSAFE.objectFieldOffset(field);
return (T) UNSAFE.getObject(object, l); 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); long offset = UNSAFE.objectFieldOffset(data);
UNSAFE.putObject(object, offset, buffer); UNSAFE.putObject(object, offset, value);
} }
public static int getIntField(Field f, Object obj) public static int getIntField(Field f, Object obj)
@ -75,4 +79,23 @@ public class UnsafeHacks
long offset = UNSAFE.objectFieldOffset(data); long offset = UNSAFE.objectFieldOffset(data);
UNSAFE.putInt(object, offset, value); 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));
}
} }