lundi 4 novembre 2019

AbstractMethodError when calling overridden method of abstract class from a class compiled at runtime

Let me first summarize what exactly I'm trying to do. Basically, I'm using the JavaCompiler package to compile a class at runtime that extends my superclass "Player". The only thing that I know will be in the subclass is that it will extend Player and override the abstract method calcMove(). To load the class at runtime after it has been compiled, I create a URIclassloader object to load the class file after it has been created. The problem is that when I try to run the calcMove method from the instantiated object (by using java.lang.reflect)

Here's bascially what I'm doing:

//to hold the compiler output
ByteArrayOutputStream compilerOut = new ByteArrayOutputStream();

                //compile
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

int compilationResult = compiler.run(null, compilerOut, compilerOut, playerFile.getAbsolutePath());

if (compilationResult == 0) {

System.out.println("File " + playerFile.getName() + " compiled successfully");

} else {

//code 99 as compile error
System.err.println(compilerOut.toString());
System.exit(99);
}

Once the file is compiled, I use this code to make a uriclassloader to load the class (the upload folder contains the source and class files) The className is determined from the file name. Then I use java Reflection to instantiate the class as an object and cast it as a Player:

URL classUrl = new File("upload").toURI().toURL();

ClassLoader classLoader = URLClassLoader.newInstance(new URL[]{classUrl}, ClassLoader.getSystemClassLoader());
                classLoader.loadClass(className).asSubclass(Player.class);

Class<?> studentCustomClass = Class.forName(className, true, classLoader);


Constructor<?> constructor = studentCustomClass.getConstructor();
Player studentPlayer = (Player) constructor.newInstance()

The instantiation apparently works until I get to where it calls calcMove. I create a new "Game" class that takes 2 Player arguments, within this Game class I call the calcMove() method from the custom class objects (cast as Players). However I'm getting an AbstractMethodError Exception because its trying to call the abstract calcMove method from Player instead of the implemented version from the subclass.

So, I'm wondering, is there some reason why it's trying to call the abstract version from the parent class instead of the version from the class I just compiled? (As far as I can tell, java considers the object I create to be a type of the subclass class rather than just a Player class , which I couldn't instantiate anyway since its abstract) Right now I'm using java Reflection to force it to call the calcMove fucntion from the object

Method calcmove = players[0].getClass().getMethod("calcMove");

calcmove.invoke(players[0]);

I'd like to avoid using reflect at his point in the code for security reasons. So why does this work, but this:

players[0].calcMove();

Gives me an AbstractClassError?





Aucun commentaire:

Enregistrer un commentaire