我有一个类被实例化为一个序列的一部分(一个方法通过一个随机的类列表,并创建每个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("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());
}
}
}
答案 0 :(得分:1)
您可以使用sun.misc.Unsafe#allocateInstance(MyClass.class)来构造实例,而无需实际调用构造函数。有关详细信息,请参阅http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/。
答案 1 :(得分:0)
如果允许修改命令行,则应尝试使用java代理。代理是一个基本上在类加载之前挂钩的类,可以修改类的字节码。
为了在不是JVM专家的情况下修改字节码,javassist是一个很好的库,它允许你编写一些类似java的代码并在方法之前/之后注入它。
所以基本上,你需要
这里有一些关于代理人的最小信息:
https://zeroturnaround.com/rebellabs/how-to-make-java-more-dynamic-with-runtime-code-generation/
和javassist教程非常清楚:
http://jboss-javassist.github.io/javassist/tutorial/tutorial.html
当然这是一个肮脏的黑客,但你要求它
答案 2 :(得分:0)
你不需要来“干扰”构造函数。这是固定的。您只需调用,Constructor<T>.newInstance(...).
如果您需要设置对象的其他属性,请调用setter。如果不存在setter,则无法执行此操作。