MyClassLoader.java
class MyClassLoader extends ClassLoader {
private String dirName;
public MyClassLoader(String dirName) {
this.dirName = dirName;
}
public Class findClass(String name) throws ClassNotFoundException {
try {
byte[] b = readFile(dirName+name+".class");
return defineClass(name, b, 0, b.length);
} catch(Exception e) {
throw new ClassNotFoundException(e.toString());
}
}
private static byte[] readFile(String fileName) throws IOException {
File f = new File(fileName);
FileInputStream fis = new FileInputStream(f);
byte[] r = new byte[(int)f.length()];
fis.read(r);
fis.close();
return r;
}
}
MyPlugin.java
interface MyPlugin {
public String getValue();
}
PluginOne.java
class PluginOne implements MyPlugin {
public PluginOne() {
}
public String getValue() {
return "This is plugin number 1";
}
}
Exception in thread "main" java.lang.IllegalAccessError: class PluginOne cannot access its superinterface MyPlugin
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:502)
at java.lang.ClassLoader.defineClass(ClassLoader.java:431)
at MyClassLoader.findClass(LoadPlugin.java:47)
at java.lang.ClassLoader.loadClass(ClassLoader.java:299)
at java.lang.ClassLoader.loadClass(ClassLoader.java:255)
at LoadPlugin.main(LoadPlugin.java:11)
This occurs even if I attempt to load the Interface first using my class loader.
Thanks in advance,
Kevin
[java] Java Plugin System
Hello,
I''ve been having some trouble creating a system that can dynamically load ''plugin'' classes into a game I''m creating. I''ve searched the forum and googled, but I could not find a solution to the error I''m having.
Here''s the relivant code, followed by the exception I''m getting.
Have MyClassLoader call its super(); in the first line of its constructor is what I would try first... Not really sure about the usefulness of this extending classloader exercise though. Especially when you can do something like this:
Or code to that effect.
public class Renderer {}public class OGLRenderer extends Renderer{}public class SoftwareRenderer extends Renderer{}public int main(String[] args) { Renderer myrenderer; ... try { myrenderer = new OGLRenderer(); } catch (Exceptionclassnotfound or whatever) { myrenderer = new SoftwareRenderer(); } finally {handle the mess}}
Or code to that effect.
No dice on the super call. (Isn''t it implicit anyway?)
The reason I want a system like this is similar to a Quake modification style system.
The reason I want a system like this is similar to a Quake modification style system.
I have never extended class loaders myself, the standard Class.forName was always good enough for my simple plug-ins. However, aren''t class loaders in a hierarchy and you need to pass a super class loader when explicitely creating a new one? Otherwise the new class loaders cannot access classes loaded by ther loaders.
Class.forName was always good enough for me as well, extending ClassLoader is a tricky thing to get right at the best of times.
[S-Type] [V-Script]
[S-Type] [V-Script]
One thing to make sure... are you loading MyPlugin before PluginOne? If not, then the VM can''t see PluginOne''s interface. Also, you need a call to resolveClass(Class c) at the end of defineClass() if you wish to instantiate that class. Let me know how you get on with these 2 suggestions
Stu
Stu
ServantOfGlaaki is right. You need to load all parent classes before the plugin.
First make it work, then make it fast. --Brian Kernighan
The problems of this world cannot possibly be solved by skeptics or cynics whose horizons are limited by the obvious realities. We need men and women who can dream of things that never were. - John Fitzgerald Kennedy(35th US President)
Do not interrupt your enemy when he is making a mistake. - Napolean Bonaparte
First make it work, then make it fast. --Brian Kernighan
The problems of this world cannot possibly be solved by skeptics or cynics whose horizons are limited by the obvious realities. We need men and women who can dream of things that never were. - John Fitzgerald Kennedy(35th US President)
Do not interrupt your enemy when he is making a mistake. - Napolean Bonaparte
Ok, here''s what I''ve got so far, still the same exception.
I''m curious if the error has something to do with the fact that the PluginOne class might not have permissions to the MyPlugin interface? Since the interface should be loaded already. Regardless, explicitly loading the interface works.
Thanks again,
Kevin
I''m curious if the error has something to do with the fact that the PluginOne class might not have permissions to the MyPlugin interface? Since the interface should be loaded already. Regardless, explicitly loading the interface works.
Thanks again,
Kevin
import java.io.*;public class LoadPlugin { public static void main(String args[]) { try { String dirname = readString("Directory Name? "); String classname = readString("Class Name? "); MyClassLoader mcl = new MyClassLoader(dirname); mcl.loadClass("MyPlugin"); //Can comment this line out for the same result Class c = mcl.loadClass(classname); MyPlugin p = (MyPlugin)c.newInstance(); System.out.println(p.getValue()); } catch (Exception e) { System.out.println(e.toString()); } } private static String readString(String prompt) { try { StringBuffer buffer = new StringBuffer(); System.out.print(prompt); System.out.flush(); int c = System.in.read(); while (c!= ''\n'' && c != -1) { buffer.append((char) c); c = System.in.read(); } return buffer.toString().trim(); } catch (IOException e) { return ""; } } }class MyClassLoader extends ClassLoader { private String dirName; public MyClassLoader(String dirName) { super(); this.dirName = dirName; } public Class findClass(String name) throws ClassNotFoundException { try { byte[] b = readFile(dirName+name+".class"); return defineClass(name, b, 0, b.length); } catch(Exception e) { throw new ClassNotFoundException(e.toString()); } } public Class loadClass(String name) throws ClassNotFoundException { return loadClass(name, true); //According to docs this should call resolveClass } private static byte[] readFile(String fileName) throws IOException { File f = new File(fileName); FileInputStream fis = new FileInputStream(f); byte[] r = new byte[(int)f.length()]; fis.read(r); fis.close(); return r; }}
When you are loading classes instead of the VM, you have to load any parent classes yourself. They are not loaded automatically.
First make it work, then make it fast. --Brian Kernighan
The problems of this world cannot possibly be solved by skeptics or cynics whose horizons are limited by the obvious realities. We need men and women who can dream of things that never were. - John Fitzgerald Kennedy(35th US President)
Do not interrupt your enemy when he is making a mistake. - Napolean Bonaparte
First make it work, then make it fast. --Brian Kernighan
The problems of this world cannot possibly be solved by skeptics or cynics whose horizons are limited by the obvious realities. We need men and women who can dream of things that never were. - John Fitzgerald Kennedy(35th US President)
Do not interrupt your enemy when he is making a mistake. - Napolean Bonaparte
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement