Re: Dynamic Class Loading & AbstractMethodError
Peter Jones - JavaSoft East <[email protected]>
| Newsgroups | gmane.comp.java.sun.rmi |
|---|---|
| Message-ID | <20051028235849.GB1833@east> |
> I've decided to follow the advices of the article "The Lifecycle of an
> RMI Server", and change somethings in setup of my applications.
>
> [1] I've started the rmiregistry like this: rmiregistry
> -J-Dsun.rmi.loader.logLevel=VERBOSE,
> with no CLASSPATH defined.
>
> [2] Launched a CustomClassLoader that listen's for HTTP requests in
> port 3000. And placed all the classes of my system in a directory that
> is used by the CustomClassLoader.
>
> [2] I've placed in a directory called server the following files:
> Task.class; TaskMessage.class; MyServerInterface.class;
> MyServerInterfaceImpl.class; MyServerInterfaceImpl_Stub.class
>
> [3] Launched the server like this: java -cp server
> -Djava.security.policy="policy.all"
> -Djava.rmi.server.codebase="http:/localhost:3000/"
> MyServerInterfaceImpl
[That should be "http://" (two slashes)?]
> [4] And i've noticed, seeing the rmiregistry console,once i ran the
> server, that the downloaded classes were: Task.class;
> MyServerInterfaceImpl_Stub.class; MyServerInterfaceImpl.class
It seems odd that MyServerInterfaceImpl would be downloaded; in
general neither the registry nor the client should need the server's
remote implementation class, and it is often not made available from
the server's codebase.
> --First question: Why is it always necessary to place all the classes
> of my application in the classpath of my server, if they are
> downloaded by the rmiregistry? Is it because of the codebase? RMI has
> to download the classes to force the codebase to be set? But if that
> is true, the classes on the classpath of the server, are only
> necessary to launch the server itself, because they will always be
> downloaded from the CustomClassLoader, am i right?
I don't quite understand these questions, perhaps because I don't
understand exactly what you mean by "CustomClassLoader": the
description above sounds like an HTTP server for class files, not a
class loader in the Java virtual machine sense.
> [5] Second i've launched my client like this: java -cp client
> -Dsun.rmi.loader.logLevel=VERBOSE -Djava.security.policy=policy.all
> -Djava.security.manager MyClient
>
> In the client directory were only these files: MyClient.class;
> MyServerInterface.class; Task.class
>
> And, when i ran the client, the downloaded files were:
> TaskMessage.class; MyServerInterfaceImpl_Stub.class
>
> And this time all went well.
>
> With the verbose flag's i've noticed that when rmiregistry
> downloaded the file, the output message is "found via codebase". But
> when is the client it says "found via defaultLoader... defined by
> http:/localhost:3000". That's confusing... Java states that is using
> defaultLoder, but is downloading the classes..."found via codebase"
> is the proper message i think...
This difference in the logging messages is related to somewhat obscure
details of the dynamic class loading mechanism: "defaultLoader" here
refers to the loader passed as the third argument to the method
RMIClassLoader.loadClass(String codebase,
String name,
ClassLoader defaultLoader)
and in this case, when unmarshalling the result of the getTask()
invocation, it is the defining loader of the class of the stub
(MyServerInterfaceImpl_Stub) through which the getTask invocation was
made. That loader loads classes from the stub class's codebase, and
it was created and first used when the stub was unmarshalled from the
result of the registry lookup. For an invocation on that stub (like
getTask), it is then typically the "default" class loader when
unmarshalling the result of the invocation.
> But the real question is...If i don't put the TaskMessage.class
> inside the directory of server, even if this is one of the classes
> that the rmiregistry doesn't download(see point [4]), the client
> will not work(it complains of NoDefClassFoundError) Why? Is it
> always necessary to duplicate the number of classes? One in the
> customclassloader and in the classpath of the server? In this case,
> the TaskMessage.class has to be in both places? Otherwise it will
> not work?
Again, I don't quite follow these questions. If TaskMessage is not in
the server's class path, a NoClassDefFoundError will occur on the
server side because the server's code has a direct symbolic reference
to it.[*]
Regarding the original problem:
>> 5- And for some reason, that i don't understand, java throws the following
>> error: AbstractMethodError " "StubFileName".getTask(); " In the following
>> line of the client source code:
>>
>> "Task t = stub.getTask();"
>>
>> Does anyone has a sugestion?
That would seem to indicate using the wrong version of the stub class,
one that does not implement the interface's getTask() method.
-- Peter
[*] not unlike why a client application must have the remote interface
that it invokes in its class path, as recently discussed here:
http://archives.java.sun.com/cgi-bin/wa?A2=ind0510&L=rmi-users&P=1536
===========================================================================
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