2016-01-22 36 views
0

我正在嘗試使用此枚舉並添加新材料。 任何未被移除的東西在其他地方都有很強的依賴性,即使如此,根據mod作者的說法,這幾乎是Java字節的限制,所以沒有太多的工作空間。在運行時創建並覆蓋Java Enum對象[GregTech/minecraft]

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.InvocationTargetException|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());}} 

任何幫助或建議表示讚賞,他們在球員在鍛造IRC是真的不知道任何。

+0

我懷疑你可以用簡單的反射來做到這一點。但問題是,你真的需要破解'enum'類型還是隻需要實現接口'IColorModulationContainer'和'ISubTagContainer'? – Holger

+0

除此之外,您應該以可讀的方式格式化源代碼,並停止在每條語句之間使用日誌語句來污染代碼。這是非常難以閱讀的。 – Holger

+0

除非它包含在材料枚舉中,否則它是沒有加載或甚至沒有處理的無用代碼。這就是爲什麼在運行時修改它是唯一真正的選項AFAIK。實際上,考慮到以前做過這個的人是Forge程序員的主要人員之一,但我沒有想到這完全在我的能力範圍之內。 我知道這不是一個標準的用例,它不符合枚舉的要點,但有時你只需要擴展某人的工作。 (我很歡迎試試爲什麼不這樣做) – Draknyte1

回答

1

JVMs應該阻止這種鬼鬼祟祟的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)); 
    } 
} 

但是,不要指望這個解決方案將持續...