A new development snapshot. It's now possible to write your own custom assembly class loader. This is the recommended pattern:
class MyCustomClassLoader extends ClassLoader
protected Class findClass(String name)
// TODO: forward call to other class loader or load class and call defineClass()
protected URL findResource(String name)
// TODO: forward call to other class loader or find resource somewhere
protected Enumeration findResources(String name)
// TODO: forward call to other class loader or find resources somewhere
If you delegate to other class loaders, you should be careful to avoid loops in the delegation path. If you want to change the resource loading delegation order, you can override
getResource[s]() instead of
findResource[s]() relatively safely, but if you want to change the delegation order for classes you need to be more careful, because you cannot replace any classes that are defined in the assembly.
Of course, you can also reuse existing class loader classes. Here's an example with URLClassLoader:
class MyCustomClassLoader extends java.net.URLClassLoader
super(new java.net.URL, new ikvm.runtime.AssemblyClassLoader(asm));
// see below why calling addURL() is safer than passing it to the super constructor
Note that custom assembly class loader classes and their single argument Assembly constructor must be accessible from the assembly that they are applied to.
ikvm.runtime.AssemblyClassLoader instance that is passed in as the parent class loader is a bit funny. It supports loading classes and resources from the assembly, but it effectively does this by magically delegating back to the custom class loader (without actually calling it, otherwise you'd get infinite recursion.) This means that classes from the assembly can be loaded via the parent class loader, but they report the custom class loader instance as their class loader.
The custom assembly class loader is constructed when someone calls
getClassLoader() on a class defined in that assembly for the first time, but what should
getClassLoader() return while the custom class loader is being constructed? For consistencies sake, I've decided to apply some magic here and to make it return the object that is currently being constructed. This implies that you should call the base class constructor ASAP, because as long as you haven't done this the ClassLoader instance is in an unitialized state. After calling the base class constructor you can do additional work to configure your custom class loader, but you should take into account that while you are setting up your instance data, if you do anything that causes a class or resource to be loaded via your class loader, that your methods may run while initialization has not yet been completed. Note that this can only happen for the initiating thread. All other threads that call
getClassLoader() will be blocked while the constructor is runnning. If the constructor throws an exception, the initiating call to
getClassLoader() will see the exception, but all other calls will return the partially initialized class loader object.
Too Much Magic?
I certainly hope not, but I have to admit this is a scary feature. I recommend only writing your own custom assembly class loader if you really understand Java class loaders and there is no alternative.
Finally, please do send me feedback on this feature (even if it's a simple "I like it" or "It sucks"). I plan on backporting this to the 0.36 release, so it's important to get this right.
- More changes to keep up the pretense that an AssemblyClassLoader has already loaded all classes in the assembly.
- Made AssemblyClassLoader public and moved it to ikvm.runtime package.
- Allow non-public custom assembly class loaders (if they are defined in the same assembly).
- Fixed ClassLoader.getSystemClassLoader() to return the custom assembly class loader for the main executable, if one is defined, even if the java.class.path or java.ext.dirs system property is set.
- Restructured AssemblyClassLoader.GetProtectionDomain() to avoid calling any code while holding the lock.
Binaries available here: ikvmbin-0.37.2855.zip.