Mam poważny problem z Class loaderem, siedzę z tym już jakiś czas i nie mogę nic wymyślić. Po krotce przedstawie problem.
Mam klasę którą chcę wywoływać poprzez Class loadera, jar nie może być w classPath ponieważ w zależności od uruchomionego pakietu mają ładować się odpowiednie klasy.
W ładowanym pliku jar mam klasę CobraClass która implementuje interfejs IMyInterface. Klasa ta w konstruktorze wywołuje konstruktor klasy CobraPostClass, która wyświetla odpowiedni komunikat. (Oczywiście w docelowym programie jest inny kod, tutaj dałem tylko taki żeby można było łatwo zrozumieć).
Po pobraniu klasy z jar chcę wywołać statyczną metodę createCobraClass która zwraca nam interfejs IMyInterface i rzutować ją do IMyInterface, niestety wtedy wyskakuje mi "Exception in thread "main" java.lang.ClassCastException: cobra.CobraClass cannot be cast to cobra.IMyInterface"
Problem natomiast nie występuje jeżeli z Class loadera usunę metodę public Class<?> loadClass(String name)
Poniżej przedstawiam żródła, gdyby czegoś brakowało będę dopisywał na bieżąco.
ClassLoader:
import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.jar.JarFile;
public class ExternalClassLoader extends ClassLoader {
private String jarFile = null;
public ExternalClassLoader(String name) {
super(ExternalClassLoader.class.getClassLoader());
jarFile = name;
}
@Override
public Class<?> loadClass(String name)
throws ClassNotFoundException {
return findClass(name);
}
protected Class findClass(String name) throws ClassNotFoundException{
byte[] classBytes = null;
try{
classBytes = loadClassBytes(name);
}
catch (IOException e) {
//throw new ClassNotFoundException(name);
return super.loadClass(name);
}
Class cl = defineClass(name, classBytes, 0, classBytes.length);
if (cl == null)
throw new ClassNotFoundException(name);
return cl;
}
private byte[] loadClassBytes(String name) throws IOException{
URL URLConnection = new URL("jar:file:"+jarFile+"!/"+name.replace(".", "/")+".class");
JarURLConnection conn = (JarURLConnection)(URLConnection.openConnection());
InputStream input = conn.getInputStream();
byte[] bytes = new byte[input.available()];
input.read(bytes);
return bytes;
}
}
IMyInterface:
package cobra;
public interface IMyInterface {
public void registerObserver(String name);
public String printRegisteredObserver();
public void printExternalLocation();
}
CobraClass:
package cobra;
import java.io.File;
import cobra.post.CobraPostClass;
public class CobraClass implements IMyInterface {
private String fileName;
private File nameOfFile;
private CobraClass(File fileName) {
this.nameOfFile = fileName;
}
public static IMyInterface createCobraClass(File name){
return new CobraClass(name);
}
@Override
public String printRegisteredObserver() {
return fileName + nameOfFile.getAbsolutePath();
}
@Override
public void registerObserver(String name) {
this.fileName = name;
}
@Override
public void printExternalLocation() {
new CobraPostClass();
}
}
CobraPostClass:
package cobra.post;
public class CobraPostClass {
public CobraPostClass() {
System.out.println("Print External Class");
}
}
No i samo wywołanie klas:
String jarFile = "c:\\jar\\temp\\testjar.jar";
ExternalClassLoader classLoader = new ExternalClassLoader(jarFile);
Class klasa = classLoader.findClass("cobra.CobraClass");
Method[] m = klasa.getMethods();
Object c = m[0].invoke("createCobraClass", new File("c:\\plik.txt"));
IMyInterface cccc = (IMyInterface)c;
cccc.registerObserver("moja nazawa");
System.out.println(cccc.printRegisteredObserver());