[2249] in java-interest
More class loader info.
daemon@ATHENA.MIT.EDU (Chuck McManis)
Wed Sep 27 10:43:24 1995
Date: Tue, 26 Sep 1995 14:10:08 -0700
From: cmcmanis@scndprsn.eng.sun.com (Chuck McManis)
To: java-interest@java.Eng.Sun.COM, chanda@PRPA.Philips.COM
> The testloader is simple, just loads class from InputStream.
> In fact I just copied it from WWWClassLoader.java to try it out.
You missed a crucial point. ClassLoader is abstract and requires its
subclasses to define the method:
Class loadClass(String name, boolean resolve);
You must use this exact signature. Now in your case you could add this
method and then use it to call your loadClass method that takes an
input stream.
This error message:
loadtest.java:154: class testloader is an abstract class. It
does not define java.lang.Class loadClass(java.lang.String, boolean)
from class java.lang.ClassLoader.
Is telling you that you didn't define a method that overrides the abstract
loadClass method.
This error:
ClassLoader loader = new testloader(myinputstream);
^
loadtest.java:155: No method matching loadClass(java.io.InputStream)
found in class java.lang.ClassLoader.
Is telling you that class ClassLoader doesn't define the method you are
invoking (loadClass with an inputStream). This code is confused on two
points:
1) testloader constructs an object of type "testloader" but
you are putting it into a Classloader (widen cast)
2) Then you try to refer to it as a testloader without a cast.
So first, make testloader concrete by defining loadClass(string, boolean)
Then change your test program to read:
testloader loader = new testloader(myinputstream);
> But "testloader" is not an abstract class. In fact did'nt I just
> define it ? Whats so abstract about that !! I checked in
> ClassLoader.java to make sure I had definitions for all abstract
> classes. This was the only one.
Methods with *Different* signatures do not override, only matching
signatures.
> 3)
> So far no one talks about implementing interfaces and such. After this
> I read comments on "Secrets of the ClassLoader" which says that I
> should define an interface loaded on the "system" side of the class
> loader, and then cast the new object to that interface object and
> invoke it using the interface. (Should be titled "Unsolved Mystries of
> the ClassLoader" don't you think ?)
Interfaces are implemented just like classes except that they don't have
any implementation, just method signatures. My original "secrets of the
class loaders" message was targeted toward people with a bit more base
understanding of how Java works. I can see how it is both mysterious and
opaque without the basics.
> I'm kinda lost at this point.
> So how does one do this ?? Is there some complete set of
> "how-to-implement-your-own-classloader" ??
No there is not.
> Can some of the Java-guru's help out ? I've already wasted TWO days on
> this.. and this was that part of Java that I was looking forward to ..
Then it can't be a waste now can it :-).
> I'm kinda lost at this point.
---------------------------------------------------------------------------
Class Loader BASICS
-------------------
When a request is made by a Java program to instantiate a class, the virtual
machine first checks to see whether or not that class has already been
loaded. If the class has not been loaded, then the VM invokes the class loader
to load the class file. The class loader that the VM invokes, depends on the
class loader of the class making the request.
Every class contains a "cbLoader" field, which tells the VM what class loader
loaded it. If it was loaded by the system (the primordial class loader) then
that field is null. Otherwise it points to the class block for the class loader
that loaded you.
There are two ways that classes can "demand" that classes be loaded, one
is through the statement "new ClassName(...)" and the other is through
the static function "forName" in class Class. So Class.forName("myclass")
will request that myclass be loaded. In alpha you can also say simply
new("myclass") but that was removed from the language.
When a demand is made to load a class, the class loader of the invoking
class is called invoked. The method called is "loadClass" and parameters
passed are the name of the class to be loaded and a boolean that says
whether or not the class needs to be resolved. The initial class loaded
_always_ needs to be resolved so sometimes people will define a method
in their classloader with this signature loadClass(String classname) and
implement it with "loadClass(classname, true)" (why this isn't in the base
class loader class I can't explain.)
Now loading a class kicks off a recursive operation to load the class and
all of its dependencies. This is accomplished by the internal operation of
resolveClass() which recursively calls loadClass on your class loader for
each class that the class you started with depends on, and the classes they
depend on.
The result of a loadClass is a pointer to a subclass of Class that is the
class of the object you want to instantiate. A new object can be created
with the instanceOf() method which is part of Class class (and thus all
of its subclasses). Note that instanceOf() calls the public null constructor
that is the one defined "public ClassName() { ... }" if you don't have
such a constructor you won't be able to instantiate it. (that is a feature
BTW)
Now once you have this object, you'll probably want to invoke some method
on it. However if you try to cast it to the loaded class you will get
class cast exception because the class loaded by the class loader is
considered to be distinct from the same class loaded by the native loader.
To get around this you use an interface. Interfaces, unlike classes, merely
promise that the method you are invoking is in the object you are invoking.
If the object implements the interface, the object's class is searched for
the matching method and then that method is invoked.
--Chuck
-
Note to Sun employees: this is an EXTERNAL mailing list!
Info: send 'help' to java-interest-request@java.sun.com