2013-04-05 2 views
1

У меня есть класс будет экземпляр как часть последовательности (метод проходит через случайный список классов и создает 3 экземпляров каждый)приоритета или модификация конструктора Java класса во время выполнения

Я пишу одно из классы в этом списке (обратите внимание: все классы существуют в одном пакете)

Я не могу изменить исходные файлы любого из других классов, и мне нужно либо остановить создание экземпляров всех классов, следуя моим собственным, либо переопределить их конструктор с пустым методом.

Я до сих пор пытался использовать отражение, и смотрел на загрузчике классов, но не могу понять, как сделать это

я могу получить ссылку на конструктор с отражением, но до сих пор не смогли помешать это

редактировать -> мысль я имел (динамически переписывать и перекомпилировать целевые классы), код компилируется, но им получает исключение, которое останавливает новый класс от компиляции

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

Edit-> следующее это код Я предоставляю на основе комментариев ниже

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

+0

Просьба указать наименьшее количество кода, что иллюстрирует то, что вы пытаетесь сделать. Код должен быть достаточно полным, чтобы кто-то мог его скопировать и вставить, а также скомпилировать и запустить, чтобы получить точное поведение, о котором вы просите. (Не стесняйтесь оставлять заявления об импорте.) –

+0

@dasblinkenlight Я понял, что отражение было потерянной причиной, я надеюсь, что я смогу сделать это через classLoader или с трансформаторами, я написал заменяющий загрузчик классов, который бы сделал трюк, но проблема в том, что он быть внутренним классом для моего, и мне нужно будет заменить загрузчик по умолчанию на него во время выполнения – Wirt

ответ

0

Если вам разрешено изменять командную строку, вы должны попробовать java-агенты. Агент - это класс, который обычно перехватывает перед загрузкой классов и может изменять байт-код класса. Чтобы изменить байт-код, не являясь экспертом JVM, javassist - хорошая библиотека, которая позволяет вам написать некоторый Java-код и ввести его до/после методов.
Так в основном, вам нужно

  1. Написать агент, изменять конструктор ваших врагов классов
  2. Launch в 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 file – Wirt

0

Вам не нужно , чтобы «вмешаться» в конструктор. Это фиксированная. Вам нужно всего лишь позвонить его, с Constructor<T>.newInstance(...). Если есть другие свойства объекта, который вам нужно установить, вызовите сеттеры. Если сеттеры не существуют, вы не сможете этого сделать.

+0

Я пытаюсь остановить существующий конструктор от вызова, либо просто прекратив создание экземпляра, либо заменив/переопределив существующий конструктор пустым – Wirt

Смежные вопросы