It's also worth mentioning, while I was fixing a synchronization or
concurrency bugs, I found it very hard to reason about the state of
public mutable fields in a number of api objects, I'd do a lot of
defensive copying and making sure I've published them safely, however it
is difficult to ensure these objects don't escape from locked or safely
published scope.
While I understand that people have an expectation to be able to modify
these fields, it would be much simpler if these object were immutable
and people simply made a new copy instead of mutating them. A number of
api classes also contain publicly accessible mutable arrays.
It's possible to retain the serial form of these classes, while
replacing arrays with immutable lists.
This would improve performance and reduce memory consumption.
I understand that to do so however, there would be a certain level of
pain for developers.
Regards,
Peter.
On 6/09/2015 9:41 PM, Peter wrote:
On 5/09/2015 1:49 AM, Greg Trasuk wrote:
On Sep 4, 2015, at 5:26 AM, Dawid Loubser<da...@travellinck.com>
wrote:
And given the vision, experience and efforts of people like Peter, it
would almost be criminal to not break free from an old standard, to
miss
the potential of what may be.
Speaking of which, I’ve always wondered, Peter, if you could tell us
a little about the Jini systems you’ve built and worked with in the
past, and some of the issues you’ve seen in production? It would be
great if we on the list could share some experiences - that would
highlight areas where the standards get in the way, and we could
change them. We are the standards body for Jini, after all.
I can't say I've run data centres filled with Jini systems. I haven't
experienced difficulties writing or deploying services, although I
don't do this on a large scale, however I've had trouble with security
policy files and proxy trust. I don't like using URL's for policy
files, so I created a policy service. I've included the service api
for the policy service in org.apache.river.api.security.RemotePolicy
Basically when a node starts, it registers a RemotePolicy service with
the lookup service, an automated admin client receives an event,
contacts the service and populates it with its security policy.
The RemotePolicy service requires the policy provider to implement
org.apache.river.api.security.RevocablePolicy. In this case the
implementation of the RemotePolicy service hasn't been contributed,
however it is pretty obvious how it works.
The abstract class, org.apache.river.api.security.PermissionGrant, is
an object version of the grant statement in a policy file. The
implementations of this class are package private as is the serial
form of these classes.
Unlike PermissionCollection, PermissionGrant's are immutable, they're
used in all River policy implementations. The class allow
PermissionCollection's to be created on demand, with all the latest
dynamic and static grants, ordered optimally to eliminate unnecessary
permission checks.
Since policy implementations are nested, another interface,
org.apache.river.api.security.ScalableNestedPolicy allows the top
level policy to collect all PermissionGrant's from underlying
policies, before creating an optimally ordered PermissionCollection
for policy permission implies checks.
These interfaces and classes make it much easier to manage security
policies, belonging to to an administrator in a shared djinn. Each
administrator can idenfity their services, using an Entry, then filter
appropriately. The RemotePolicy service only uses a bootstrap proxy,
no codebase is downloaded. It is recommended to use secure
endpoints. Calls executed on the RemotePolicy service are run with
the administrator's subject.
For services that are Activatable, or require a thread after
construction is completed, an interface
org.apache.river.api.util.Startable, is provided, if a service
implements this interface, Phoenix, or the start package will call it
after constructing the service. Jini was never updated to Java 5, in
this version of Java, the JMM was updated, I think if the original
Jini team had done so, they would have done something like this. It's
the simplest and safest way of exporting a service after construction,
although the Startable interface doesn't just provide for safe
exporting, it can be used to start threads or utilities the service
uses after construction as well.
When an object is instantiated, the jmm guarantees a memory fence will
occur that ensures that all threads will see the fully constructed
object. When an object allows a reference to itself to escape during
construction, there is no guarantees that other threads will see the
fully constructed object. For synchronized access to fields, all
accesses must be synchronized, so even if another thread uses
synchronization, if the object wasn't safely published there's no
guarantee that a thread will see the fully constructed object.
I've found the best place to discuss the JMM is the concurrency
interest mail list.
The final thing I wish to discuss, is the new classes ing
org.apache.river.api.net.* RFC3896URLClassLoader and Uri.
Uri is a RFC3986 compliant Uri, it isn't Serializable and since it is
based on the RFC3986 standard it is also not going to change. This
class is relevant throughout River, from normalization of codebase
annotations to replication of Codebase.implies functionality. Uri,
unlike java.net.URI (RFC2396 based) it is fully compliant with the
standard and doesn't extend it, this is very important from a
performance perspective, as bitshift operations can be utilised during
normalization.
RFC3986URLClassLoader, uses URL's that are parsed to be compliant with
RFC3986, this is to avoid DNS calls in
java.security.SecureClassLoader, this is both for performance and
security reasons.
I'd like to see these classes added to the public api, anyone that
uses URLClassLoader with network URL's should use
RFC3986URLClassLoader instead. Uri will have even more relevance for
Java 9, since modular codebase annotations in Java 9 will be RFC3986
compliant. Talking to the devs on OpenJDK, they've tried making
java.net.URI RFC3986 compliant, but it causes test failures for them,
also because java.net.URI extends the previous standard, their RFC3986
version will probably also need to, so they'll miss out on some
serious performance benefits provided by bitshift operations.
As for the future, once I have security sorted, I plan to make
publicly available, a lookup service on IPv6, using the discovery
announcement protocol over IPv6 multicast. Here people will be able
to register their own services and others will be able to use them.
The advantage that River has over web services is it's distributed,
unlike its web service cousins that are client-server based. For
instance, the cloud is client server based, with resources in a data
centre. In the distributed model, nodes can both consume services
and provide them.
As for problems with the standards, I'd suggest the proxy trust model
is overly complex, I'd like to revise it.
Otherwise there is a lot to like and a lot of well thought out
designs, but there are some parts that time has not been so kind to,
that need repairing by modern standards.
Regards,
Peter.
For myself, the big issue was always ease of writing and deploying
services, which is why I wrote the Harvester application container
back in the day, and the River Container (which I really must get
around to thinking up a new name for) more recently. When you get
more than a few machines involved, things get complicated to manage,
although I haven’t done a system big enough to show the kind of QOS
issues that Dennis’ Rio project was designed to address.
Cheers,
Greg Trasuk