2007/5/4, Tom Tromey <tromey@xxxxxxxxxx>:
Yup. I'd suggest that instead of thinking of the solution in terms of writing a class loader, think about it in terms of writing some code that simply returns a byte[] that is the class contents.
This is already done. Although this downloading code is called from loadClass. The byte[] array is then transformed to a Class object thanks to defineClass methods.
Then call this downloading code from VMClassLoader.loadClass. How you implement the downloading is up to you, but it turns out to be pretty simple to re-use URLClassLoader for this... just treat the .class file at the URL as a resource, not a class, and don't use the loadClass family of calls on your delegate URLClassLoader at all.
Basically when a new() is performed and the class not already loaded, doesn't the VM calls loadClass() family of calls? How to avoid loadClass() from ClassLoader, download our byte[] (as explained above) and create a Class object out of it without calling defineClass() ?
Martin> We have done some basic tests and this seemed to work. However, when Martin> trying with a more complete program, it appears that it throws Martin> IllegalAccessException making me think that some security is added Martin> when using the defineClass() on core API. For this sort of a thing more details are needed. At least a full stack trace. But if you follow the above this may be moot.
I think we got more on this one and every problem seems to be related. Whether the class code is loaded from bootstrap (thanks to native code VMClassLoader.loadClass() ) or thanks to a Java ClassLoader, the Class object is finally created with native function defineClass() -called directly from native loadClass in the first case (bootstrap) or called with VMClassLoader.defineClass() in the second case (Java ClassLoader) but it is finally the same function. There are two differences when calling native defineClass() in the two cases: - Protection Domain, which we could easely set to null without any difference - The classloader itself Our debbuging shows that the VM is actually able to find a Class from the ClassLoader without calling loadClass() but just using the reference we give on this classLoader when calling defineClass(). This is done when the VM has to load a class on which depends the class we wanted to load. This results in a compromised situation: - If forcing ClassLoader to null when calling defineClass from our ClassLoader (to have a similar call as if we were the real bootstrap) the VM is unable to find the classes which should be automatically loaded (since it can't be loaded from bootstrap and a null pointer to ClassLoader means bootstrap). ClassNotFoundException. - If giving the right reference to our ClassLoader, IllegalAccessException are thrown, when constructor (and thus calls to super() ) is executed. java.lang.IllegalAccessException: method is not accessible at java.awt.Frame.<init>(Frame.java:246) at java.awt.Frame.<init>(Frame.java:234) at test2.Test1.<init>(Test1.java:9) at test2.Test.<init>(Test.java:8) at test2.Test.main(Test.java:11) It seems that whether the ClassLoader is set to null or not is the discriminating security parameter. And we can't set it to null because of the problem explained above, about dependencies. I think we have to find where this security is managed -at runtime and not when loading class- and modify its behavior... thanks for any help and sorry if I didn't understand your first solution, I'm all ears for more details. martin
Tom