2013-04-05 51 views
1

一個Java類構造函數我有一個類被實例化作爲序列的一部分(一個方法遍歷一個類的隨機列表,並創建每個的3個實例)重寫或修改在運行時

我寫的一個(注意:所有的類都存在於同一個包中)

我無法修改任何其他類的源文件,我需要停止所有類的實例化,或者重寫它們帶有空方法的構造函數。

我一直在使用反射到目前爲止已經試過,並一直在尋找的類加載器,但無法弄清楚如何做到這一點

我能夠獲得對構造與反思,但到目前爲止,參考已經無法來干擾它

編輯 - >一個思想,我有(動態地重新編寫和重新編譯的目標類),代碼編譯但即時得到來自編譯停止新類的異常

private void reWrite(String name) {//throws IOException { 
    try{ 
    File sourceFile = new File("/temp/" + "name" + ".java"); 
    System.out.println("file defined"); 
    FileWriter writer = new FileWriter(sourceFile); 
    System.out.println("filewriter defined"); 

    writer.write("public class "+name+" extends Creature {/n" 
      + "private static int instanceCount = 0;/n" + "public "+name+"() {/n" 
      + " instanceCount++;/n" + "}/n" + "public void doTurn() {}/n" 
      + "public final void creatureDestroyed() {/n" 
      + " instanceCount--;/n" + "}/n" 
      + "public final int getInstanceCount() {/n" 
      + " return instanceCount;/n" + "}/n" + "}/n"); 
    writer.close(); 
    System.out.println("written"); 

    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
    StandardJavaFileManager fileManager = compiler.getStandardFileManager(null,null,null); 

    fileManager.setLocation(StandardLocation.CLASS_OUTPUT, 
      Arrays.asList(new File("/temp"))); 
    // Compile the file 
    compiler.getTask(
      null, 
      fileManager, 
      null, 
      null, 
      null, 
      fileManager.getJavaFileObjectsFromFiles(Arrays 
        .asList(sourceFile))).call(); 
    System.out.println("compiled"); 
    fileManager.close(); 
    }catch(Exception e){ 
     System.out.println("fuckery"); 
    } 
} 

編輯 - >以下是代碼我根據下面的評論提供

try { 
     getW = (World.class.getDeclaredMethod("getWorld")); 
     getW.setAccessible(true); 
     theWorld = getW.invoke(World.class); 
     getK = (Creature.class.getDeclaredMethod("die")); 
     getK.setAccessible(true); 
    } catch (NoSuchMethodException exc) { 
     System.out.println("Method Not Found."); 
    } catch (Exception e) { 
     System.out.println("well shit"); 
    } 

    try { 
     f = World.class.getDeclaredField("locations"); 
     f.setAccessible(true); 
     locations = f.get(theWorld); 
     loc = (ArrayList<Creature>) locations; 
    } catch (Exception e) { 
     System.out.println("well poop"); 
    } 
    if (loc.size() > 0 && !allMine) { 
     for (int i = 0; i < loc.size(); i++) { 
      if (loc.get(i).getClass() != Colonial.class 
        && loc.get(i).getClass() != Plant.class) { 

       try { 
        getK.invoke(loc.get(i)); 
       } catch (Exception e) { 

       } 

       loc.set(i, new OpenLand()); 
      } 
     } 
    } 
+1

你不能通過反射來「干涉」構造函數:如果可以的話,那將是一個重大的安全漏洞。 – dasblinkenlight 2013-04-05 01:27:36

+0

請提供最少量的代碼,說明您正在嘗試做什麼。代碼應該足夠完整,以便某人可以複製並粘貼它並編譯並運行它,以獲得您所詢問的確切行爲。 (隨意留下進口報表。) – 2013-04-05 01:29:26

+0

@dasblinkenlight我認爲反射是一個失敗的原因,我希望有一種方式,我可以通過類加載器或變壓器做到這一點,我寫了一個替代類加載器,可以做到這一點,但問題是它有成爲我的內部類,並且我需要在運行時用它替換默認的加載器 – Wirt 2013-04-05 01:30:27

回答

0

如果您被允許修改命令行,您應該嘗試java代理。代理是一個基本上在類加載前掛鉤的類,並且可以修改類的字節碼。 爲了在不作爲JVM專家的情況下修改字節碼,javassist是一個不錯的庫,它允許您編寫一些類似java的代碼並在方法之前/之後注入它。
所以基本上,你需要

  1. 編寫使用該代理

在這裏,您有關於代理一些最起碼的信息是修改你的敵人類

  • 啓動的構造函數的JVM代理:
    https://zeroturnaround.com/rebellabs/how-to-make-java-more-dynamic-with-runtime-code-generation/
    和javassist教程真的很清楚:
    http://jboss-javassist.github.io/javassist/tutorial/tutorial.html
    當然這是一個骯髒的黑客,但你要求它

  • +0

    不幸的是我唯一能碰到的是我的東西。 java文件 – Wirt 2013-04-05 04:45:01

    0

    你不需要需要'干擾'的構造。它是固定的。你只需要調用它,用Constructor<T>.newInstance(...).如果還有其他屬性需要設置,請調用setters。如果制定者不存在,則不能這樣做。

    +0

    我想阻止現有的構造函數被調用,要麼停止實例化或用空的替換/覆蓋現有的構造函數 – Wirt 2013-04-05 04:44:28