dimanche 15 février 2015

Nullpointer in method when loading a class with Classloader

Okay, so my problem occurs when I try and change a JLabel's text, but the error only occurs when I run the method when the class has been loaded using Classloader.


I am loading the class from a jar using the code below, that works fine and the default constructor is called.



public void loadPlugins(){
try {
File path = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath().toString().substring(1));
File file = new File(path.getParent() + "/plugins/");

for (int i = 0; i < file.listFiles().length; i++) {
if (file.listFiles()[i].getName().contains(".jar")){
File a = new File(file + "\\" +file.listFiles()[i].getName());
URL url = a.toURL();
URL[] urls = new URL[]{url};
ClassLoader cl = new URLClassLoader(urls);
Class cls = cl.loadClass("BotCode." + file.listFiles()[i].getName().replace(".jar", ""));
cls.newInstance();
}
}
}catch (Exception e){
e.printStackTrace();
}
}


The next part of code also works fine, if the classes have been compiled and don't need to be loaded, if that makes any sense at all.



public void readIni(String command, String params){
try {
File path = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath().toString().substring(1));
File file = new File(path.getParent() + "/plugins/");

for (int i = 0; i < file.listFiles().length; i++) {
if (file.listFiles()[i].getName().contains(".jar")){
System.out.println(file.toURI());
URL url1 = new URL("jar:" + file.toURI() + file.listFiles()[i].getName() + "!/commands.ini");
Ini ini = new Ini(url1);

if (ini.get("main").toString().indexOf(command) != -1){
File a = new File(file + "\\" +file.listFiles()[i].getName());
URL url2 = a.toURL();
URL[] urls = new URL[]{url2};

ClassLoader cl = new URLClassLoader(urls);
Class cls = cl.loadClass("BotCode." + file.listFiles()[i].getName().replace(".jar", ""));

Method method = cls.getDeclaredMethod(ini.get("main").get(command), String.class);
System.out.println(this);
method.invoke(this, params);

}
}
}
} catch (Exception e){
e.printStackTrace();
}
}


When I call readIni() from a completely seperate class, with two strings it completes it with no problem. For example, if the ini contained "!addQueue=addQueue", and I passed "readIni("!addQueue", "test")", it would run the method addQueue("test") on the class that was loaded.


The method addQueue is:



public static void addQueue(String name){
queue.add(name);
System.out.println("TEST 1");
Date date = new Date(System.currentTimeMillis());
String RTime = date.toString().substring(date.toString().indexOf(":") - 2, date.toString().indexOf(":") + 3);
queue.add(RTime);
System.out.println("TEST 2");
updateQueue();
System.out.println("TEST 3");
jLabel14.setText("" + queue.size()/2);
System.out.println("TEST 4");
}


The coded completes up to print("TEST 2"), but it gets stuck on updateQueue();, the error provided is:



java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at BotCode.Plugins.readIni(Plugins.java:41)
at BotCode.Bot.newMessage(Bot.java:123)
at BotCode.hbWebsocket.onMessage(hbWebsocket.java:109)
at org.java_websocket.client.WebSocketClient.onWebsocketMessage(WebSocketClient.java:248)
at org.java_websocket.WebSocketImpl.decodeFrames(WebSocketImpl.java:375)
at org.java_websocket.WebSocketImpl.decode(WebSocketImpl.java:158)
at org.java_websocket.client.WebSocketClient.run(WebSocketClient.java:185)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
at BotCode.QueuePlugin.updateQueue(QueuePlugin.java:351)
at BotCode.QueuePlugin.addQueue(QueuePlugin.java:323)
... 12 more


updateQueue() looks like this:



public static void updateQueue(){
//System.out.println(queue.get(0));
System.out.println(queue.size());
if (queue.size() == 0) jLabel8.setText("-");
if (queue.size() >= 1) {
System.out.println("test");
jLabel8.setText("- " + queue.get(0));
} else jLabel8.setText("-");
if (queue.size() >= 3) {
jLabel9.setText("- " + queue.get(2));
} else jLabel9.setText("-");
if (queue.size() >= 5) {
jLabel10.setText("- " + queue.get(4));
} else jLabel10.setText("-");
if (queue.size() >= 7) {
jLabel11.setText("- " + queue.get(6));
} else jLabel11.setText("-");
if (queue.size() >= 9) {
jLabel12.setText("- " + queue.get(8));
} else jLabel12.setText("-");
}


"at BotCode.QueuePlugin.updateQueue(QueuePlugin.java:351)" is "jLabel8.setText("- " + queue.get(0));".


The rest of the Queue code can be found here.


So the code is getting a NullPointerException on changing a JLabel's text, which seems very strange as it only happens when the class files are not in the output directory but are loaded using a class loader. Sorry for the large amount of code, but any help finding the solution is greatly appreciated. If I have left out any code that you think would be important, let me know and I'll add it.


Thanks!


-Tom






Aucun commentaire:

Enregistrer un commentaire