gpt4 book ai didi

java - 在运行时创建和覆盖 Java 枚举对象 [GregTech/minecraft]

转载 作者:行者123 更新时间:2023-12-01 10:33:36 25 4
gpt4 key购买 nike

我正在尝试使用这个枚举并添加新 Material 。任何尚未删除的内容在其他地方都有硬依赖关系,即使如此,根据 mods 作者的说法,这几乎达到了 java 字节限制,因此实际上并没有太多的空间可以使用。

GregoriousT 提到“有一种方法。Overmind 使用 Reflection 黑了 Enum 来添加他自己的东西。不知道他是怎么做到的,也不知道如果你问他,他需要多长时间才能回复。”

我们正在讨论的枚举: http://pastebin.com/g0aJ2Qjd

所以我只是问,我该怎么做?

这就是我当前尝试抛出的[FML]: Variable m:1|newInstance|public java.lang.Object sun.reflect.DelegatingConstructorAccessorImpl.newInstance(java.lang.Object[]) throws java.lang .InstantiationException,java.lang.IllegalArgumentException,java.lang.reflect.InitationTargetException | false 在客户端崩溃之前。 (为了方便阅读,删除了日志代码)

当前尝试:

public class MaterialsNew {

public static void getGregMaterials() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException{
Utils.LOG_WARNING("Stepping through the process of Greg's materials.");

Constructor<?> con = Materials.class.getDeclaredConstructors()[0];
java.lang.reflect.Method[] methods = con.getClass().getDeclaredMethods();
for (java.lang.reflect.Method m1 : methods) {
if (m1.getName().equals("acquireConstructorAccessor")) {
m1.setAccessible(true);
m1.invoke(con, new Object[0]);}
}
Field[] fields = con.getClass().getDeclaredFields();
Object ca = null;
for (Field f : fields) {
if (f.getName().equals("constructorAccessor")) {
f.setAccessible(true);
ca = f.get(con);
}
}
Method m = ca.getClass().getMethod( "newInstance", new Class[] { Object[].class });
m.setAccessible(true);
Materials v = (Materials) m.invoke(ca, new Object[] { new Object[] { "NEWMATERIAL", Integer.MAX_VALUE } });
System.out.println(v.getClass() + ":" + v.name() + ":" + v.ordinal());}}

感谢任何帮助或建议,Forge IRC 的人也不太确定。

最佳答案

JVM 应该能够防止这种偷偷摸摸的 enum 实例创建。因此,您必须要么使用可能很快就会解决的缺陷,要么深入 JRE,以至于最轻微的更改都可能会破坏它。

这里有一个技巧,适用于 Oracle 当前的 JRE 8,也许也适用于 JRE 7,而且非常简单:

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.util.EnumSet;

public class EnumHack {
public static void main(String[] args) throws Throwable {
Constructor<Thread.State> c
= Thread.State.class.getDeclaredConstructor(String.class, int.class);
c.setAccessible(true);
MethodHandle h=MethodHandles.lookup().unreflectConstructor(c);
Thread.State state=(Thread.State)h.invokeExact("FLYING", 42);
System.out.println("created Thread.State "+state+"("+state.ordinal()+')');
System.out.println(EnumSet.allOf(Thread.State.class).contains(state));
}
}

但不要指望这个解决方案会持续存在......

关于java - 在运行时创建和覆盖 Java 枚举对象 [GregTech/minecraft],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34945282/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com