在运行时创建和覆盖Java枚举对象[GregTech/minecraft] [英] Creating and overriding Java Enum Objects at Runtime [GregTech/minecraft]

查看:80
本文介绍了在运行时创建和覆盖Java枚举对象[GregTech/minecraft]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用该枚举并添加新材料. 尚未删除的所有内容在其他地方都具有严格的依赖性,即使如此,根据mods作者的说法,这几乎达到了Java字节的限制,因此无论如何,实际上没有太多的工作空间.

I'm trying to work with this enum and add new materials. Anything not already removed has hard dependencies elsewhere, even still, this is nearly at the java byte limit according to the mods author so there isn't really a lot of room to work with anyway.

GregoriousT提到:有一种方法.Overmind用Reflection入侵了Enum,添加了自己的东西.不知道他是如何做到的,也不知道如果你问他,他需要花多长时间来回复事情."

GregoriousT mentioned "There is one way. Overmind hacked the Enum using Reflection to add his own stuff. No Idea how he did that and also no idea how long he takes to reply to things if you ask him."

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

Enum we're talking about: http://pastebin.com/g0aJ2Qjd

所以我只是问,我将如何处理?

So I simply ask, how would I go about this?

这是我当前尝试抛出的内容[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.InvocationTargetException|false 在客户端崩溃之前. (已删除日志代码以便于阅读)

This is what my current attempt throws [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.InvocationTargetException|false before the client crashes. (Log code removed for easy reading)

当前尝试:

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上的家伙也不是很确定.

Any help or suggestions appreciated, they guys over at the Forge IRC weren't really sure either.

推荐答案

JVM应该阻止这种卑鄙的enum实例创建.因此,您必须使用可能会很快解决的缺陷,或者侵入JRE如此之深的地方,以至于一点点的更改都可能破坏它.

JVMs are supposed to prevent such sneaky enum instance creations. So you have to either use a flaw that soon might get solved or hack such deep into the JRE that the slightest change may break it.

这是一个技巧,它可以与Oracle当前的JRE 8一起使用,也许也可以与JRE 7一起使用,并且非常简单:

Here is a trick which works with Oracle’s current JRE 8, perhaps JRE 7 as well, and is surprisingly simple:

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));
    }
}

但是不要期望这个解决方案能够持续下去……

But don’t expect this solution to persist…

这篇关于在运行时创建和覆盖Java枚举对象[GregTech/minecraft]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆