Custom Class Loaders

D

Dave Rudolf

Hi all,

I'm playing around with class loaders, and I seem to be having some
problems. Suppose that I write my own class loader, like so:

///////////////////////////////////////////

import java.io.*;

public class StreamClassLoader extends ClassLoader
{
public StreamClassLoader()
{
}

private static byte[] readData( final InputStream inStream,
final int length )
throws IOException
{
final byte[] data = new byte[ length ];
int readSoFar = 0;
while( readSoFar < length )
{
readSoFar += inStream.read(
data, readSoFar, length - readSoFar );
}
return data;
}

private Class loadClass( final String expectedClassName,
final byte[] classData )
{
return defineClass( classData, 0, classData.length );
}

public Class loadClass( final String expectedClassName,
final InputStream inStream,
final int length )
{
return loadClass( expectedClassName, readData( inStream, length ) );
}
}


///////////////////////////////////////////

Now, if I want to use this class loader, I can't just use Class.forName(
String ), as it will just use the default loader. Instead, I have to do
something like:

StreamClassLoader loader = new StreamClassLoader();

//...

Class someClassType;
try
{
someClassType = loader.loadClass( "some.ClassType" );
}
catch( NoSuchClassException nsce )
{
File file = new File( "some/ClassType.class" );
someClassType = loader.loadClass(
"some.ClassType",
new FileInputStream( file ),
file.getLength() );
}


Okay, I can live with that. But the problem is that if I am reading objects
off of an ObjectInputStream, it uses the default class loader.
Interestingly, an ObjectOutputStream does not need the class loader to write
an object of this type. I assume that it just uses the object's class
directly.

So my question is: how do I link the custom class loader to an
ObjectInputStream? It would also be nice get Class.forName(...) to work
also, so that other parts of the code would not have to know about the
custom loader.

Thanks,

Dave.
 
L

Lee Fesperman

Dave said:
Hi all,

I'm playing around with class loaders, and I seem to be having some
problems. Suppose that I write my own class loader, like so:

///////////////////////////////////////////

import java.io.*;

public class StreamClassLoader extends ClassLoader
....

///////////////////////////////////////////

Now, if I want to use this class loader, I can't just use Class.forName(
String ), as it will just use the default loader. Instead, I have to do
something like: ...

Class.forName() has a form that takes a classloader.
Okay, I can live with that. But the problem is that if I am reading objects
off of an ObjectInputStream, it uses the default class loader.
Interestingly, an ObjectOutputStream does not need the class loader to write
an object of this type. I assume that it just uses the object's class
directly.

So my question is: how do I link the custom class loader to an
ObjectInputStream? It would also be nice get Class.forName(...) to work
also, so that other parts of the code would not have to know about the
custom loader.

I believe the only way is to use ObjectInputStream inside a class loaded by your
classloader.
 
V

VisionSet

In what situations are class loaders and custom class loaders used?

The only time I've used even the default one is to force a static block to
run at start up so the app would fail cleanly if the classes were not
present.
 
D

Dave Rudolf

The reason I asm using it is for distributed applications, e.g. if one
process sends an object to another, but the receiver does not have the
compiled byte code for the object's class, then the sender would also have
to transmit the class file down to the receiver.

Another reason would be to allow "plug-ins", so the user can download a new
feature, which could be a class file or jar, and the program could just scan
for such files and decide to load them at run-time.

I have also heard of class loaders that decypher an encrypted jar file in
order to protect the intellectual property, etc. From a cryptographic view,
this seems lame, but it's one possible use for a class loader.

Dave.
 
D

Dave Rudolf

Lee Fesperman said:
I believe the only way is to use ObjectInputStream inside a class loaded by your
classloader.

I haven't tried your suggestion yet, but have my doubts that it would work.
Or rather, if it does work, then does the system implicitly link the stream
to the class of the object that created it? That seems like really bad
design to me. Then the behaviour of the stream varies based on some random
state of the system and the programmer has no good way of knowing that the
difference exists and has to do nasty things to get it to work properly.
 
L

Lee Fesperman

Dave said:
I haven't tried your suggestion yet, but have my doubts that it would work.
Or rather, if it does work, then does the system implicitly link the stream
to the class of the object that created it? That seems like really bad
design to me. Then the behaviour of the stream varies based on some random
state of the system and the programmer has no good way of knowing that the
difference exists and has to do nasty things to get it to work properly.

You made me look ;^)

I checked Sun's documents and could not find a clear statement of what actually happens.
I did get the distinct impression that readObject() in ObjectInputStream uses the
current context, that is, the classloader of the calling class. So the classloader is
selected at readObject() rather than at new ObjectInputStream(). Sorry, if I implied
otherwise (I did say "use ObjectInputStream inside ...").

I doubt that it is a bad design. It really has to work in the current context. For
instance, the docs for Class.forName(String) says it uses "the defining class loader of
the current class". Thus, it would be reasonable default for readObject() also.

Unfortunately, this is all guesswork so far. You'll have to try it out for yourself.
Kindly report back.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top