2

シーケンスの一部としてインスタンス化されているクラスがあります (メソッドはクラスのランダムなリストを通過し、それぞれの 3 つのインスタンスを作成します)

そのリストのクラスの 1 つを作成しています (注: すべてのクラスが同じパッケージに存在します)。

他のどのクラスのソース ファイルも変更できず、自分のクラスに続くすべてのクラスのインスタンス化を停止するか、空のメソッドでそれらのコンストラクターをオーバーライドする必要があります。

これまでリフレクションを使用してみましたが、クラスローダーを見てきましたが、これを行う方法がわかりません

リフレクションを使用してコンストラクターへの参照を取得できますが、これまでのところ干渉できませんでした

編集 - >私が考えていた(ターゲットクラスを動的に書き直して再コンパイルする)、コードはコンパイルされますが、新しいクラスのコンパイルを停止する例外が発生します

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

編集->以下は、以下のコメントに基づいて提供しているコードです

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

3 に答える 3

1

コマンド ラインの変更が許可されている場合は、Java エージェントを試してください。エージェントは、基本的にクラスロードの前にフックし、クラスのバイトコードを変更できるクラスです。JVM の専門家でなくてもバイトコードを変更できるようにするために、javassist は Java のようなコードを記述してメソッドの前後に挿入できる優れたライブラリです。
したがって、基本的には、

  1. 敵クラスのコンストラクターを変更するエージェントを作成する
  2. そのエージェントを使用して JVM を起動します

ここには、エージェントに関する最小限の情報が
あり
ます
。 jboss-javassist.github.io/javassist/tutorial/tutorial.html
もちろんこれは汚いハックですが、あなたはそれを求めました

于 2013-04-05T03:07:02.010 に答える
1

実際にコンストラクターを呼び出さずに、 sun.misc.Unsafe#allocateInstance(MyClass.class)を使用 してインスタンスを構築できます。詳細については、 http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/を参照してください。

于 2014-10-29T13:27:48.470 に答える
0

コンストラクターに「干渉」する必要はありません。修正されました。設定する必要があるオブジェクトの他のプロパティがある場合は、セッターを呼び出しますConstructor<T>.newInstance(...).セッターが存在しない場合は、それを行うことはできません。

于 2013-04-05T03:12:57.407 に答える