As your well aware, River has some issues with ClassLoaders during
deserialization.
I've had some thoughts and ideas, about how River might provide a simple
ClassLoader tree (and the way we package our service interfaces) that
may solve some of these issues. Your feedback, thoughts and ideas
would be much appreciated.
System ClassLoader
|
\|/
|
Extension ClassLoader (Includes DynamicPolicyProvider)
|
\|/
|
Jini Platform ClassLoader
|
______________________|_______________________
| |
\|/ \|/
| |
Application ClassLoader Smart Proxy ClassLoaders * many
The Jini Platform ClassLoader would contain the Jini Platform and
Include Service Interface jars and dumb proxy's (reflective) in
ProtectionDomains with no permission grants.
The Application ClassLoader would contain Service implementations,
including Reggie, Norm, Mahalo, etc, Client Applications and
ServiceUI's. The Application ClassLoader itself may have further Child
ClassLoaders.
Smart Proxy ClassLoaders - There would be one ClassLoader per smart
proxy (Service), which can contain any number of jar's or external 3rd
party software library's, all isolated in the Smart Proxy's ClassLoader
and only visible to Application code through common Service Interfaces
and classes in the Jini Platform ClassLoader or it's parents. It's
implementation doesn't concern the Application. By allowing Permissions
to be dynamically granted by CodeSource Certificates, or by CodeSource,
the proxy can utilise publicly signed, shared jar archives, to provide
privileged functionality. Provided the client has authorised it. This
may even be prior to Proxy Trust Verification.
All the usual Method Invocation Constraints and Proxy Trust Verification
still apply, as each CodeSource has a separate ProtectionDomain, a Proxy
will not be granted any permissions until after Verification, however as
mentioned above, a Proxy might bundle with it another CodeSource in the
same ClassLoader under a separate ProtectionDomain that already has some
permissions granted by way of Signer Certificates.
I've had some thoughts where Codebase services might fit in too, a
CodeBaseAccessClassLoader implementation could utilise the ServiceID in
a weak hashtable to locate ClassLoaders during unmarshalling for the
Smart Proxy's. The ServiceID would be annotated in addition to Other
annotated codebase information when the smart proxy communicates
utilising JERI with its Server. A Smart Proxy ClassLoader would be asked
first to resolve classes during unarmshalling, it would delegate first
to its parent, if it fails, the context class loader would be asked to
resolve the class.
ServiceInterface codebases might consist of common Interfaces, and
Parameter / Return Value Classes, Proxy's and Client's utilise to
communicate (Services Public API), no privileges would be granted to
this code.
As a use case example, Perhaps a user might browse a list of Service
Interfaces, before selecting one, followed by lookup of that service,
upon selecting and unmarshalling a service, the ServiceUI would appear
for the user to interact with the Service.
IF YOUR INTERESTED IN OSGi READ ON.
What about OSGi?
One of the sticky issues with OSGi is Serialization, developers
utilising OSGi tackle Serialization by extending ObjectInputStream and
ObjectOutputStream and annotating a bundle name and version, to locate
the correct bundle ClassLoader upon deserailization.
As a first step, OSGi can reside where the Application ClassLoader is
shown in the above tree, as such service implementations and client
applications that utilise OSGi can utilise Jini Services. This won't be
done through the OSGi Service Registrar and it won't stop developers
from creating OSGi services that utilise Jini Services, but I don't
think Jini Services should be registered with the OSGi service registrar
directly, they have different concerns and it is simpler not to do so.
Marshalled Streams could be annotated with a either package names (&
version) or jar/bundle names and a message digest and the ServiceID
(where applicable) to assist identifying the correct ClassLoader or
downloading the correct jar for unmarshalling. Instead of asking the
context ClassLoader to resolve classes after failing to resolve a class
with the Smart Proxy's ClassLoader an OSGi Bundle ClassLoader would be used.
This doesn't mean that at some point in the future River won't itself
utilise OSGi directly to manage its own modularity.
We can add bundle Manfiests to jsk-platform.jar and other jar's without
requiring OSGi.
OSGi has a ConditionalPermissionAdmin service and a PermissionAdmin
service, we might be able to provide an OSGi service that implements
these by wrapping our DynamicPolicyProvider, we'll see, stay tuned.
The really hard part for full OSGi integration is management of the
Smart Proxy's ClassLoaders during deserialization, since many services
can potentially share the same codebase (bundle), however trust concerns
and permission grants may vary, meaning that identical bundles with
identical versions would have to reside in different ClassLoaders, this
differs from OSGi semantics.
The best compromise for now appears to be to place the Smart Proxy
ClassLoaders outside of OSGi, and allow Jini to isolate them from the
Application Space, In this way, OSGi applications can utilise non OSGi
Jini Services. Instead Jini / River provides the Abstraction /
Isolation layer.
If we want to modularise River, a good way to begin to would be to make
some of River's service implementation's Norm, Outrigger, etc OSGi
bundles. Bundle activation can then cause these services to be Exported
and Registered with the Jini Service Registrar. That would enable life
cycle management of those services without stopping River etc.
Regards,
Peter.