Comments below...

Cheers,

Greg.
On Wed, 2010-05-26 at 07:27, Peter Firmstone wrote:
> Hi Dennis,
> 
> Looking back at my earlier reply when you presented the ClassLoader 
> structure for Rio, I was unintentionally insensitive.
> 
> I didn't mean to pull it apart, probably not the right approach, Rio is 
> a success in it's own right!
> 
> What I should have said and I may not have communicated too well is that 
> I'm introducing a way for Service Proxy's to utilise ClassLoader 
> visibility for maximum API class sharing.  It is a new feature, to give 
> Service implementers the power to share their Service API's, with as 
> much local JVM visibility as the Jini Platform Service API's have.
> 

Um.. why?  API classes are the client's problem.  The service
implementer just makes a few interfaces, and possibly a few domain
classes (data types) available, and if the client wants to use them,
includes the api-jar in its classpath.  I'd argue that in almost all
cases, the client is compiled against a particular api, so can go ahead
and include those jars in its runtime classpath as well.  If a proxy has
its own classes, the codebase classloading mechanism (along with
preferred classes) just puts those classes into their own classloader,
and will garbage-collect the whole classloader if the proxy instance
becomes unreferenced.  Surely, even smart proxies will not be so huge
that a little duplication is a problem.

Now, if you're after a generic, portable module mechanism, like OSGi but
with remotely specifiable modules, that's fine, but I'm not convinced
that's in Jini/River's purview.


> As I pointed out there is a compromise, that Service API classes cannot 
> be garbage collected.  I think that if this can be well managed, using a 
> Permission, then it should not affect uptime for critical applications.
> 
I'm hard pressed to think of a case where an api class changes without
requiring a redeployment of its clients, which, even if you're in an
application container, would trigger garbage collection of the whole
classloader.  Can you give an example?

> With great power comes great responsibility... yada yada yada.
> 

In my books, simplicity always wins.

> Cheers,
> 
> Peter.
> 
> Peter Firmstone wrote:
> > Peter Firmstone wrote:
> >> IDENTICAL TO ANOTHER MESSAGE IN THREAD: Re: Maven repository Entry 
> >> was Re: Codebase service?
> >>
> >> Note: A permission will be required to allow a proxy to introduce new 
> >> Service API during unmarshalling to prevent against denial of service 
> >> attacks.
> > However in the absence of this permission, the additional ServiceAPI 
> > jar could be downloaded into the proxy's own ClassLoader, that would 
> > require a ClassLoader even for a dumb proxy with an interface you 
> > didn't want to load into your Service API space.  This would enable 
> > unmarshalling of that Proxy.  If you, at a later point decided to load 
> > that interface into your Service API space, I think you still wouldn't 
> > be able to interact with this particular proxy using it, since the 
> > interface class identity would be different.
> >
> > Denial of service here means unfairly growing a JVM's use of non 
> > garbage collectable classes.  Any ideas how to control download proxy 
> > memory consumption.
> >>
> >> Hi Dennis,
> >>
> >> It sounds like you remain unconvinced or don't have a need to use common
> >> interfaces for your service proxy's?
> >>
> >> So I guess it's a tread lightly approach, make the feature available to
> >> those that want common Service API (The same interface instance for all
> >> proxy's implementing that interface, so they can be used in collections
> >> or batch operations), for maximum sharing of proxy's with differing
> >> implementations, but let those that don't want to publish their API
> >> continue doing what they usually do.  A configuration parameter should
> >> be able to set the desired behaviour.
> >>
> >> The approach I've taken is a simple approach to a complex problem,
> >> alternative approaches leave the complexity in the hands of the
> >> implementer, my approach will enable them to practically ignore it.
> >>
> >> Before you write it off though, to answer your earlier question, I'll
> >> further explain the ClassLoader structure between multiple nodes.
> >>
> >>                    CLIENT NODE
> >> ________________________________________________
> >> |                                                |
> >> |             System                             |
> >> |           ClassLoader                          |
> >> |                |                               |
> >> |            Extension                           |
> >> |           ClassLoader                          |
> >> |                |                               |
> >> |          Jini Platform &                       |
> >> |           Service API                          |
> >> |           ClassLoader                          |
> >> |                |                               |
> >> |       _________|___                            |
> >> |      |             |                           |
> >> | Application    Smart Proxy                     |
> >> | ClassLoader    ClassLoader's                   |
> >> |________________________________________________|
> >>
> >>
> >>                   SERVICE NODE
> >> ________________________________________________
> >> |                                                |
> >> |             System                             |
> >> |           ClassLoader                          |
> >> |                |                               |
> >> |            Extension                           |
> >> |           ClassLoader                          |
> >> |                |                               |
> >> |          Jini Platform &                       |
> >> |           Service API                          |
> >> |           ClassLoader                          |
> >> |                |                               |
> >> |       _________|_____________________          |
> >> |      |             |                 |         |
> >> | Service Imp    Smart Proxy      Parameter Impl |
> >> | ClassLoader    ClassLoader's    ClassLoader's  |
> >> |________________________________________________|
> >>
> >>
> >> All Proxy and Service implementations are free to vary at will, proxy
> >> instances can be shared in collections or iterative operations based on
> >> common Service API supertype's  All Proxy's and Services are isolated in
> >> their own Domain, the only way to communicate externally is by using
> >> interfaces and classes in upper level ClassLoaders, they can utilise as
> >> many third party libraries jar archives as they need, these will all be
> >> loaded into a single ClassLoader unique to that Service or Proxy's
> >> Codebase and Principles.  The Service or Proxy's namespace will be
> >> totally separate from Application or other Proxy implementation's,
> >> except in the case where sharing is permitted for identical
> >> implementations by the implementation developer.
> >>
> >> Service API should be carefully considered and designed, it forms the
> >> basis of network Dependency Injection, you can discover ANY Service
> >> implementation variant using the same Service API.
> >>
> >> The Service API may include other Service API or Java platform classes.
> >>
> >> public interface SimpleBookService {
> >>
> >> public Book get( Library lib, String name);
> >>
> >> }
> >>
> >> In the SimpleBookService above, given a Library and String name of a
> >> Book, a Book instance is returned by the proxy.
> >>
> >> The contents of simpleBookService-api.jar:
> >>
> >> SimpleBookService.class
> >> Book.class
> >> Library.class
> >>
> >> Let's say a client has extended the Library, with a class called
> >> PrivateLibrary, this class is an implementation class by the client,
> >> that the Service knows nothing about, the Service only uses the Library
> >> API, but it needs the PrivateLibrary.class
> >>
> >> The client makes an archive containing the PrivateLibrary.class publicly
> >> available in an archive called privateLibrary-param.jar.  This archive
> >> depends on simpleBookService-api.jar The jar URL is marshalled with the
> >> class when the parameters are sent back to the service.  When it gets to
> >> the service implementation, privateLibrary-param.jar is given it's own
> >> ClassLoader and ProtectionDomain and isn't given any Permissions.  It is
> >> used by a SimpleBookService implementation to decide which Book to
> >> return to the client, after which, it's garbage collected, eventually if
> >> PrivateLibrary isn't used again its ClassLoader is garbage collected 
> >> too.
> >>
> >> Each SimpleBookService proxy implementation will have their own
> >> ClassLoader namespace, but Client Application classes can still use any
> >> Service implementation or as many Service implementations as it can
> >> handle at the same time, all the while treating them as the same Type.
> >>
> >> One SimpleBookService implementation proxy, contains its own
> >> implementation of Book, and while the client is reading the book, it
> >> remains available from the proxy ClassLoader via the Service API Book
> >> interface, when finished reading the book, the proxy, book and
> >> ClassLoader can be garbage collected.  Tomorrow, the client might read a
> >> book from another SimpleBookService
> >>
> >> Most Service API will be relatively small bytecodes as most will be
> >> abstract or have simple implementations, the fact they're not garbage
> >> collected, doesn't matter much if the function of the node doesn't
> >> change, the API will remain limited to the subset in use, by the node.
> >>
> >> Note that Jini Platform service implementations like Reggie, Outrigger
> >> etc, will exist in Service Impl ClassLoaders and Smart Proxy
> >> ClassLoaders, only the api will be in the Jini Platform ClassLoader.
> >>
> >> Think of it as an expandable platform, everything is shared using
> >> implementations of Service API classes.
> >>
> >> It's actually a good policy to be liberal with interfaces when building
> >> the Service API classes, even with parameters and return types.  Since
> >> extending interfaces is relatively straight forward, you new interfaces
> >> will be discovered by older client software as the old interface while
> >> new implementation code discovers the new interface of your service.
> >> Older nodes will load your new interface classes into the Service API
> >> space when your new proxy versions are unmarshalled. That's why it's
> >> important to maintain backward compatibility in the Service API space.
> >>
> >> So best practise would be to create an experimental djinn group until
> >> your interfaces are stabilised and be prepared to restart your
> >> experimental group on a regular basis.
> >>
> >> I have thought about using OSGi for Service API classes to be served up
> >> so they can be garbage collected, this might work for serialization too
> >> using the context ClassLoader.  I have also thought about using
> >> ClassLoader Tree's using bytecode dependency analysis as per Tim
> >> Blackman's research.  These things start to get very complicated, just
> >> to be able to flush the Service API classes.  Wouldn't it just be better
> >> to use mutiple services that are load balanced, enabling the jvm to be
> >> restarted if we want to?
> >>
> >> There are other ways to make the Service API classes garbage
> >> collectable, such as having a tier filled with Service API ClassLoaders
> >> where each Service and Proxy lives in a child ClassLoader in the tree,
> >> however this presents the problem of what if an application wants to use
> >> many Service API's or a combination, the different Service API classes
> >> couldn't see each other from separate ClassLoaders.
> >>
> >> Something to consider, best regards,
> >>
> >> Peter.
> >>
> >> Dennis Reedy wrote:
> >>> On May 25, 2010, at 710PM, Peter Firmstone wrote:
> >>>
> >>>  
> >>>> This is a good question, which gets to the heart of the Jini's 
> >>>> pattern.
> >>>>
> >>>> I think the proposed ClassLoader structure will benefit Rio, by 
> >>>> enabling increased API commonality and class sharing among Services 
> >>>> and their clients.
> >>>>
> >>>> You can get around having to shutdown your jvm if you manage 
> >>>> evolution of your API interfaces correctly, set up a separate 
> >>>> testing Registrar, to keep new API interfaces out of your 
> >>>> deployment, until they have stabilised.
> >>>>     
> >>>
> >>> Right now the JVM doesnt need to be shut down at all, services can 
> >>> be loaded with different versions, unloaded, etc ... I think you're 
> >>> making assumptions here.
> >>>   
> >>>> Classes, once loaded into a ClassLoader, cannot be garbage 
> >>>> collected, but if your API classes don't change there is no 
> >>>> problem, when was the last time ServiceRegistrar changed it's 
> >>>> public API?   Unlike Jini's platform classes which are set in 
> >>>> stone, new API classes can be introduced into older environments.
> >>>>     
> >>>
> >>> Right, which is why service implementations get loaded into their 
> >>> own class loader. You define the 'platform' as whatever that needs 
> >>> to be for your case. For Rio it includes requisite bootstrapping and 
> >>> infrastructure technology. For River it most likely just includes 
> >>> the River 'platform', or nothing at all.
> >>> Consider ServiceStarter and the class loader created from that 
> >>> bootstrapping process. Please explain what is missing from that 
> >>> approach? Each service has it's own security policy. Why does this 
> >>> need to change? What and how does your approach improve on? To my 
> >>> eyes it seems overly complicated.
> >>>
> >>>  
> >>>> Lets take Jini Platform services as an example, in Rio's 
> >>>> ClassLoader tree below, the Interfaces for the Platform services 
> >>>> exist in the CommonClassLoader, all classes in the 
> >>>> CommonClassLoader are visible to any class in any child ClassLoader 
> >>>> below in the tree.
> >>>>
> >>>> Platform services can be shared freely among all child ClassLoaders.
> >>>>
> >>>> Now take Service-1CL and Service-2CL, lets imagine for a moment 
> >>>> that these two services both provide the same service, from 
> >>>> different or the same node, it doesn't matter, let's imagine now 
> >>>> another node with the same ClassLoader tree structure, which 
> >>>> consumes these services.
> >>>>
> >>>> These services have their service interfaces bundled with their 
> >>>> CodeSources, both on the client and at the Service, lets say that 
> >>>> Service-2CL provides the same service, but has a different 
> >>>> implementation.  Now there's a client service that consumes these 
> >>>> services, performs an operation then discards the service.
> >>>>
> >>>> Now which common API do the two service proxy's share?
> >>>>     
> >>>
> >>> Common API? The service proxies dont share anything. They are each 
> >>> loaded from an implementation of RMIClassLoaderApi
> >>>   
> >>>>  This forces you to load both proxy's into the same ClassLoader, 
> >>>> making their implementations visible to each other and the client.
> >>>>     
> >>>
> >>> Not so sure about that Peter.
> >>>
> >>>  
> >>>> By separating the API into, in your case the CommonClassLoader,
> >>>>     
> >>>
> >>> APIs are not added to the CommonClassLoader, and I would argue that 
> >>> it should not happen. You generally do not want to add classes into 
> >>> a class loader that does not get GC'd.
> >>>
> >>>  
> >>>> each with their own ProtectionDomains, all Services and clients in 
> >>>> that node, share the same API classes and can be isolated in their 
> >>>> own ClassLoader's and can have different implementations but share 
> >>>> the same common API types.
> >>>>
> >>>> The client service-param.jar is for clients who create new 
> >>>> implementations / extend parameters in API methods, the Service 
> >>>> server node will require these classes to unmarshall the 
> >>>> parameters.  Client parameter classes will never be granted 
> >>>> permissions.
> >>>>
> >>>> I'll make up some separate ClassLoader tree diagrams showing the 
> >>>> client node, the service node and the relationships between remote 
> >>>> ClassLoaders.
> >>>>     
> >>>
> >>>
> >>>  
> >>>> Peter.
> >>>>
> >>>> Dennis Reedy wrote:
> >>>>   
> >>>>> If I understand correctly I think this is the crux of the issue. I 
> >>>>> dont understand why you need to load all API classes with the same 
> >>>>> class loader. FWIW, in Rio we handle the loading (and unloading) 
> >>>>> of services with the following structure 
> >>>>> (http://www.rio-project.org/apidocs/org/rioproject/boot/package-summary.html#package_description):
> >>>>>  
> >>>>>
> >>>>>                  AppCL
> >>>>>                    |
> >>>>>            CommonClassLoader (http:// URLs of common JARs)
> >>>>>                    +
> >>>>>                    |
> >>>>>                    +
> >>>>>            +-------+-------+----...---+
> >>>>>            |               |          |
> >>>>>        Service-1CL   Service-2CL  Service-nCL
> >>>>>        AppCL - Contains the main() class of the container. 
> >>>>> Main-Class in manifest points to com.sun.jini.start.ServiceStarter
> >>>>> Classpath:  boot.jar, start.jar, jsk-platform.jar
> >>>>> Codebase: none
> >>>>>
> >>>>> CommonClassLoader - Contains the common Rio and Jini technology 
> >>>>> classes (and other declared common platform JARs) to be made 
> >>>>> available to its children.
> >>>>> Classpath: Common JARs such as rio.jar
> >>>>> Codebase: Context dependent. The codebase returned is the codebase 
> >>>>> of the specific child CL that is the current context of the request.
> >>>>>
> >>>>> Service-nCL - Contains the service specific implementation classes.
> >>>>> Classpath: serviceImpl.jar
> >>>>> Codebase: "serviceX-dl.jar rio-dl.jar jsk-lib-dl.jar"
> >>>>>
> >>>>> Certainly not as sophisticated as OSGi (or what you are 
> >>>>> targeting), but it meets the requirements of allowing multiple 
> >>>>> service versions, applying security context per class loader using 
> >>>>> the same approach as ActivateWrapper, and allows the JVM to stay 
> >>>>> running.        
> >>>
> >>>
> >>>   
> >>
> >>
> >>
> >
> >
-- 
Greg Trasuk, President
StratusCom Manufacturing Systems Inc. - We use information technology to
solve business problems on your plant floor.
http://stratuscom.com

Reply via email to