I’m trying to understand how the Java class loader works, specifically the defineClass(String,byte[],int,int) method. Let’s say I want to load the class definition for NonIntrinsicType. I know I can find the *.class file for NonIntrinsicType, serialize its contents into a byte[] called bytes, and then call defineClass(null,bytes,0,bytes.length).
The weird situation I’m having trouble understanding is, how can I get a byte[] for the class definition of something like [LNonIntrinsicType – in other words, if my application requests the class definition for an instance of NonIntrinsicType[], I don’t have a *.class file that corresponds to this class type. How would I obtain a byte[] for this type’s definition?
You’re probably wondering why I want to do this. I’m basically trying to create a network class loader, with a “Local” JVM that has class definitions on its class path, and a “Remote” JVM that does not have the aforementioned class definitions on its class path. “Remote” is encountering an instance of NonIntrinsicType[] and requests a definition from “Local” for that class type, but my “Local” JVM can’t find a class file for NonIntrinsicType[], so it fails to provde a class definition byte[] to “Remote”.
Added 9/7/2010
One thing I should have mentioned… I am using Socket and ObjectInputStream to receive messages sent to “Remote” by “Local”. I’ve created a custom extension of ObjectInputStream on the “Remote” side and overrode protected Class<?> resolveClass(ObjectStreamClass). This is the first notification my “Remote” JVM gets when an incoming message contains instances of classes that have yet to be loaded. I have another socket that I use to pass class definitions around with, so when the first socket receives an instance of a class that hasn’t been loaded, it requests a definition for that class from the “Local” JVM via the second socket.
The problem happens when my custom ObjectInputStream.resolveClass(ObjectStreamClass) gets passed an ObjectStreamClass that returns a class name for an array type (the name looks like [Lsome.ClassName;). I can easily parse out the base-level type some.ClassName and load it first – this is done in the call to NetworkClassLoader.getInstance.loadClass(), where I get a byte[] for the base-level class and then use it to call defineClass() inside that method call.
I understand now that you probably can’t get a byte[] for an array type’s class definition, so that leaves me trying to figure out how to find the Class<?> instance for the array type and return it. Here’s the code for my resolveClass method in my custom ObjectInputStream on the “Remote” JVM’s message-receiving Socket:
@Override
protected Class<?> resolveClass(ObjectStreamClass osc)
throws IOException, ClassNotFoundException{
try {
return super.resolveClass(osc);
} catch (Exception e){}
String name = osc.getName();
boolean array = name.contains("[L");
if(array) name = name.replace("[L","").
replace("[","").replace(";","");
Class<?> c = NetworkClassLoader.getInstance().loadClass(name);
if(!array) return c;
//If it's an array type, how do I obtain its corresponding
//Class<?> and return it here?
throw new ClassNotFoundException();
}
You shouldn’t need to create a definition for
[LType. If you have aClass, you can create an array of that class with reflection: