Hi Gregg,
Comments inline.
Gregg Wonderly wrote:
Peter Firmstone wrote:
Hi Gregg,
I hear what your saying.
Can I share some thoughts?
An Object's Class Type is the fully qualified class name + the
originating ClassLoader.
Once it is live in the VM, it is, but until that time, it's the source
"jar" that represents the "type" because versioning is expressed
there. Michael Warres' paper indicates this, and I think you grasp
that concept. The classloader is just a software representation of
the contents of the Jar file.
I'd like to make versioning finer grained than that, at least for
applications, I'd like to segregate at the Package level, many class
files don't change once applications mature, for Library's it makes
better sense to have a coarse grained versioning mechanism.
HTTP codebase's are part of the problem, the URLClassLoader is fixed
in the object's Type (class identity), which may change over time.
Michael Warres addressed this problem by creating a dynamic codebase
service where the URL was a cryptographic hash of the jar file
(stored data) identity.
The codebase, if not designed with versioning as part of the
expression of it, is the root cause of missing "version" information.
It's still possible to create multiple class loaders using the same
URL at different times, and have those classloaders do things like
store the Jar locally, be long lived and be resurrectable across
processes etc.
The Hash is a good solution, but does require some tooling for service
deployment and perhaps a container mechanism to make easy use of, but
it's still possible to use it manually with just a few tools.
Michael made a presentation on Service based codebases, apparently
not much code was required to implement it. We cannot directly copy
the code (interfaces etc) from the presentation due to copyright,
although we can produce functionally equivalent code.
http://www.jini.org/files/meetings/eighth/presentations/Warres/Warres.pdf
See also River-316
So the dynamic service based codebase could move around, and be
offered redundantly.
I wrote a protocol handler which would be used as
-Djava.protocol.handler.pkgs="codebase:service-dl.jar
codebase:jsk-dl.jar"
which would do service lookup, and then ask services "do you provide
service-dl.jar" and "do you provide jsk-dl.jar". It would then get
the jars from one of the services that answered yes, and return the
URLConnection to the downloaded jar as a "file:" URL.
I didn't ever deploy anything using this, because I really don't run
into problems of services working but the codebase provider not
working, very often, if at all in production. It happens occasionally
in development.
I'm really keen to see Michal's code that may be on offer from XPro, as
it supports a P2P mechanism. However please upload.
In addition, we could update/upgrade/replace the Hierarchical based
PreferredClassLoader relationship with a more flexible
DynamicClassLoader based on ClassWorlds to segregate incompatible
class packages while granting compatible classes the ability to
communicate. There is BSD licensed code that we could build on:
http://classworlds.codehaus.org/ ClassWorlds has some very elegant
simple models (easy to code & use) that may help us.
I'll try and look at ClassWorlds. The PreferredClassLoader provides
one mechanism that allows the "implementation" vs "contract" aspect of
a class/interface to be specified and thus where it is loaded from,
controlled. The fact that it defers to its "parent" when "not
preferred" just means that we could do anything with the rest of the
loading process which should really just leave 2 types of classes, the
"JVM classes" and the "contract classes". Both might have version
related details. The "JVM classes" would imply something a bit harder
to "solve" at runtime. But, the "contract classes" versioning could
be specified by some additional information in the PREFERRED.LIST
perhaps.
Understand when I said "parent" above that I'm not suggesting that
there should be a linear hierarchy of ClassLoaders. Just that the
parent is the next place to defer to.
From the above website: "The |classworlds| model does away with the
hierarchy normally associated with ClassLoaders. Instead, there is
a pool of ClassRealms
<http://classworlds.codehaus.org/apidocs/com/codehaus/classworlds/ClassRealm.html>
which can import arbitrary packages from other ClassRealms.
Effectively, |classworlds| turns the old-style hierarchy into a
directed graph."
One might give a library its own ClassLoader in each JVM for
instance, then we could make that library available to the
applications / services that depended upon it. A later version of
that library would have a separate ClassLoader so that "Jar hell" or
"Classpath Hell" (standalone JVM talk) or its distributed equivalent
"Class Type Hell" or "ClassLoader Hell" are avoided (unfair:
ClassLoaders are a blessing in disguise, they add another dimension
to namespaces).
One thing that I think makes sense is to put together some trial
version management bits of code. The mechanics are the important part
to "get right" first, and then we can survey what works and think
about how to access it and put together automatic mechanisms where
possible (the invocation layer would allow this to happen seamlessly
for version "upgrades", not so sure about downgrades). Factory style
methods could be used in iterative services where things are "loaded",
"processed" and "stored".
Have a look at River-316, I've uploaded, code with plenty of comments &
Javadoc.
I think this "space" already has had a lot of different things
evaluated and things like "classworlds" show that some "code" has
gelled in many places that provides solutions to various parts of the
problem space.
I'm interested in ClassWorlds, to me, its a poor man's Subprocess API
(shame that never eventuated maybe it will in Harmony?), it would allow
isolation between packages, and libraries, limiting classpath scope to
only that which is requried.
Gregg Wonderly
Cheers,
Peter.