Re: java.lang.InstantiationException:$Proxy0

Gregg Wonderly <[email protected]> Mon, 9 Feb 2009 18:02:28 -0600
Newsgroups gmane.comp.java.sun.rmi
Message-ID <[email protected]>
lachhman wrote:
> I mentioned in my reply "As I understand, there is no issue of codebase
> property as the sender is able to get the stub from Naming.lookup(args) and
> call remote method on this stub." 
> 
> Client is successfully calling remote methods on obtained stub, which means
> Client JVM  had got stub definition (from local classpath or using  codebase
> property) and deserialized the stub sent by the registry. 
> 
> In the code, I have not shown the remote method calls on obtained stub, but
> I have checked these are called successfully(thus no exception like
> ClassNotFound/XXX_StubNotFound something).  
> 
> 
> lachhman wrote:
>> Hi,
>>
>> I am getting this exception(java.lang.InstantiationException:$Proxy0)
>> while reconstructing the stub/proxy from the Class instance of stub/proxy.

Okay, I'm not understanding where exactly this message comes from, and that 
context is vital to understanding the source of the problem.  It's the 
"reconstructing the stub/proxy" that I am wondering about.  Are you serializing 
it to disk or some place and then loading it back?  If so, then the codebase 
will be lost when you do that at the client because the annotation is on the 
class loader, not on the instance object.

I'm just throwing and code guesses and without more information about the 
context of the exception, I'm not gonna give you anything useful I guess...

Gregg Wonderly

When you write a remote proxy object into an ObjectOutputStream, you need to 
send the codebase with it, so something like the following is the kind of 
minimal steps to do that.

// Get the output stream from where ever
ObjectOutputStream os = ...

// Write the URL[] first in the stream so that it can be activated before
// reading the proxy object.
if( srvr.getClass().getClassLoader() instanceof URLClassLoader ) {
	os.writeObject( ((URLClassLoader)srv.getClass().getClassLoader()).
		getURLs() );
} else {
	os.writeObject( new URL[0] );
}
// Write the server proxy object
os.writeObject( srvr );

and then when you read it, you'd do something like the following to make sure
that you had the annotation's codebase visible in an active classloader.

// The input stream to read from
ObjectInputStream is  = ...
// Read the array of URLs, might be empty
URL[] urls = (URL[])is.readObject();
// get the current loader
ClassLoader cld = Thread.currentThread().getContextClassLoader();
// Create the new classloader chaining up to the active one
URLClassLoader ld = new URLClassLoader( urls,
	getClass().getClassLoader(), cld );
try {
	Thread.currentThread().setContextClassLoader( cld );
	srvr = is.readObject();
} finally {
	// Restore the old context class loader
	Thread.currentThread().setContextClassLoader( ld );
}

A less tedious way is to use the MarshalledObject class which does this work for 
you behind the scenes.  Then you'd just do

os.writeObject( new MarshalledObject( srvr ) );

to write the object out, and then when you need to read it, you do.

srvr = ((MarshalledObject)is.readObject()).get();

Gregg Wonderly

===========================================================================
To unsubscribe, send email to [email protected] and include in the body
of the message "signoff RMI-USERS".  For general help, send email to
[email protected] and include in the body of the message "help".

For a list of frequently asked RMI questions please refer to:
http://java.sun.com/j2se/1.3/docs/guide/rmi/faq.html

To view past RMI-USERS postings, please see:
http://archives.java.sun.com/archives/rmi-users.html