java - ClassCastException on custom class loading -
i'm trying write scripting system in java , i've managed scripts compile , instantiate when try cast script "deftscript" throws classcasterror
thought script extends class "deftscript"
error (the important part @ least):
java.lang.classcastexception: scripts.compass cannot cast com.deft.core.scripts.deftscript @ com.deft.core.scripts.deftscriptmanager.instantiate(deftscriptmanager.java:52) ~[?:?]
the error caused this
deftscript = (deftscript)obj;
compiling , instantiating:
public static deftscript instantiate(string java) { file file = new file("./plugins/deft-core/scripts/" + java); deftscript deftscript = null; diagnosticcollector<javafileobject> diagnostics = new diagnosticcollector<javafileobject>(); javacompiler compiler = toolprovider.getsystemjavacompiler(); standardjavafilemanager filemanager = compiler.getstandardfilemanager(diagnostics, null, null); list<string> optionlist = new arraylist<string>(); optionlist.addall(arrays.aslist("-classpath", system.getproperty("java.class.path") + ";./plugins/deft-core.jar")); iterable<? extends javafileobject> compilationunit = filemanager.getjavafileobjectsfromfiles(arrays.aslist(file)); javacompiler.compilationtask task = compiler.gettask(null, filemanager, diagnostics, optionlist, null, compilationunit); if (task.call()) { object obj = null; try { string jarfile = "./plugins/deft-core.jar"; urlclassloader classloader = new urlclassloader (new url[] {new file(jarfile).touri().tourl(), new file("./plugins/deft-core/").touri().tourl()}, thread.currentthread().getcontextclassloader()); class<?> loadedclass; loadedclass = class.forname("scripts.compass", false, classloader); obj = loadedclass.newinstance(); } catch (classnotfoundexception | instantiationexception | illegalaccessexception | malformedurlexception e) { e.printstacktrace(); } deftscript = (deftscript)obj; deftscript.onenable(); } else { (diagnostic<? extends javafileobject> diagnostic : diagnostics.getdiagnostics()) { system.out.format("error on line %d in %s%n", diagnostic.getlinenumber(), diagnostic.getsource().touri()); } } return deftscript; }
calling instantiate method:
string script = "compass.java"; deftscriptmanager.instantiate(script);
deftscript.java
package com.deft.core.scripts; public abstract class deftscript { public abstract void onenable(); }
compass.java
package scripts; import com.deft.core.scripts.deftscript; public class compass extends deftscript { @override public void onenable() {} }
if default classloader loads class deftscript , .jar loading contains class deftscript, java think these 2 different classes same binary name loaded different classloaders , exception since java sees trying mix 2 different classes same thing.
the unique identification of class in java consists of binary class name , classloader used load class.
if create urlclassloader :
urlclassloader classloader = new urlclassloader (new url[] {new file(jarfile).touri().tourl(), new file("./plugins/deft-core/").touri().tourl()}, thread.currentthread().getcontextclassloader());
the second parameter tells java use current thread's classloader first load classes, , load them jar in urlclassloader if not defined in parent.
now classloader refer it's parent first , class deftscript loaded parent classloader though .jar file defines same class (by name).
this pretty article describing way works :
http://www2.sys-con.com/itsg/virtualcd/java/archives/0808/chaudhri/index.html
this helpful
Comments
Post a Comment