Apr 242005
 

Dan Moore shot me an email with a question about JavaBeans, constructors and immutability. It is something that I have been thinking about and implementing in various ways for a while because of my passion for domain modeling. My reply to Dan was one of the two ways that I prefer to implement immutability with JavaBeans. The other method, I’ll save for another entry. Here is a copy of Dan’s email and my response:

Dan’s email


Hi Brian,

I had a javabeans question and figured you’ve spent a fair bit of time wallowing in those specifications.

Does a javabean need a no arg constructor to be a proper javabean? Is this in the spec anywhere? I looked in the JAF spec and the Javabeans 1.0.1 spec, but couldn’t find anything about constructors.

Can you help me?


My response


Yeah. The spec is not exact on this because it takes into account immutable beans as well as clients instantiating beans by hand. I think the rule of thumb goes like this:

– Immutable beans are read only (only getters) and have public constructors with arguments that satisfy immutability.

– Mutable beans are read/write (getters and setters) and have public no-arg constructors.

I have found that lately my immutable beans are to restrictive for most cases and have started adding in protected no-arg constructors and protected member variables to allow sub-classes to provide mutability.

The reason I’ve started doing this is so that I can protect my domain model but allow front-ends to reuse my domain objects rather than having to copy and paste from model-beans (which I loath). For example, if I have a CD, I’d model it like this:

Now, I can use this object with something like JSF or Verge by sub-classing and using that bean on my form:

The downside here is that my objects are now not as safe and I haven’t defined the class or the member variables as final to model true immutability. This is a trade-off that I’m willing to make to reduce complexity and code redundancy. I think the next generation will allow immutable objects to be used with front-ends, but it hasn’t quite gotten there yet. The upside to all this is that by contract, my domain model remains immutable and as long as I code to the immutable class, I can ensure that I won’t have data-loss, or data-swapping.


Apr 182005
 

Working with RMI and Jini today and I found a few tidbits that I needed to set down somewhere for future reference.

1. The RMIServer assigns a unique identifier whenever a remote object is registered (UnicastRemoteObject.export() or via extension). This is the class ObjID and it uses the class UID to store the server/host namespace of the Object.

2. Registering multiple instances of the same class is legal and clients will be capable of finding all instances even if those instances are not explicitly named. This is done in an implementation specific manner, which I’d assume is round robin or least referenced object, unless the client is using the UID for the lookup (e.g. is using a custom naming system that maps an application specific name to a remote instance) (remote instance here is in fact remote stub).

3. A remote instance can be used simultaneously by multiple clients, making the need for thread safety paramount.

It appears that Jini’s lookup cache uses the remote ObjID to store instances. I haven’t verified this completely, but it is the only way I can explain the behavior of the LookupCache.

This means that the same remote instance can not be published using two separate attribute sets. Each distinct publication into the lookup service (Jini remote lookup service) must be with a unique remote object instance.

The test I have that has been failing publishes a remote object using RMI and then publishes that same instance into the Jini lookup server twice using two different attribute sets. The Jini lookup service responds correctly by assigning the remote object two separate service IDs. However, on the client the LookupCache only finds one of the two services. This implies that the lookup cache is caching based on some type of unique identifier of the remote instance. The only thing that RMI has for that is the ObjID class. Therefore, I have to assume that the lookup cache is using the ObjID class as part of the cache key or as the only cache key.

Apr 172005
 

ClassLoaders are interesting and I’ve been playing around with them a lot lately and definitely needed to jot a few things down so that I could not only remember it all but also use if for future reference and allow everyone else to do the same.

ClassLoaders reference class definitions, not data. Class definitions are the actual code and reflection information about the Class and are completely separate from the data of a Class instance, which is stored on the heap. Class definitions are loaded by the ClassLoader and stored in a special heap. If a ClassLoader is ever loading a Class definition if first should delegate (and all the out-of-the-box ClassLoaders do this) to its parent. When its parent doesn’t find the Class definition, then ClassLoader is free to load it.

Okay, let’s say we have Class MyService and Class Worker. Class MyService imports Class Worker. We also have ClassLoader P and ClassLoader C. ClassLoader P is the parent of ClassLoader C (think C-hild and P-arent). In addition, the only way that this really makes any sense whatsoever is that the ClassLoader C is the the current Thread context ClassLoader. There are a few situations that could occur:

  1. P loads MyService and P loads Worker
  2. P loads MyService and C loads Worker
  3. C loads MyService and P loads Worker
  4. C loads MyService and C loads Worker

Situation 1 means that the parent ClassLoader loads everything. The child ClassLoader doesn’t need to do anything. Situation 2 means that the parent ClassLoader loads MyService and when it tries to also load Worker it can’t. Since it is the parent, loading stops, but doesn’t fail because P can’t ask “down” to C for Worker. Situation 3 means that C loads MyService and when it tries to also load Worker, it first asks its parent for Worker, which its parent has. Situation 4 means that C loads both MyService and Worker. The parent is consulted twice, but has neither class.

Situation 2 is the sticky point here. Since the Sun JVM doesn’t fail during loading of MyService, it is tough to know what is actually going on when things start failing. Let’s elaborate on 2 for a second. Supposed MyService and Worker look like this:

In this case and with the ClassLoader situation from 2, when MyService's execute method is called, a ClassNotFoundException will occur when Worker is being instantiated. Even though C is able to load Worker AND it is the current context ClassLoader, it doesn’t matter! The golden rule of ClassLoaders, that always applies is that Classes from one ClassLoader cannot see Classes from child or sibling ClassLoaders. Since MyService is loaded by ClassLoader P, whenever it attempts to load other Classes it always starts with the ClassLoader it was loaded from. In this case, MyService will ask P for Worker. Since P doesn’t know about Worker, a ClassNotFoundException will be thrown.

Additionally, what this implies is that Class references are not bound at load time but rather delayed until they are referenced by the code that is executing. Likewise, Class definitions are bound to a ClassLoader and are constrained by that ClassLoader to only find Classes that the ClassLoader can resolve.

Must developers often refer to the fully-qualified name of Classes like:

This is only paritally true. When most people discuss ClassLoaders and Classes in articles and papers they refer to the the Classes fully-qualified name like this:

This includes the name of the Class, the package the Class is defined in and the ClassLoader that loaded it. Therefore, when Class definitions are loaded into the JVM and stored onto the special Class definition heap, they are defined using these three pieces of information.

This situation is difficult to remedy. This tough situation becomes even more difficult when MyService looks like this:

And MyService has a client that looks like this:

In this situtation, the Thread that is executing is also the Thread whose context ClassLoader has been set and it is also the service itself. Since the Thread was loaded by P, it makes little difference that I’ve changed the context ClassLoader to C. This code will still fail. So, here’s how I solved this problem.

First I realized that fully-qualified Class definitions don’t mean that the invocation of the class itself isn’t dynamic at runtime. The reason being that instances of Classes loaded by a ClassLoader can be passed around freely to instances of Classes loaded into any other ClassLoader. This is allowed only when the Class extends another Class or implements an Interface available in the other ClassLoaders (specifically because of situation 2 from above). Java holds instances in a shared pool that can be shared across Threads and have little concept of the ClassLoader that loaded them (except a reference to it and as part of its Class definition). In order to fully understand this, we need more examples. Let’s assume one more Class, AbstractWorker, from which Worker extends.

We also have to change MyService and the client so that they uses AbstractWorker.

Now, if we walk back over situation 2 from above, we can see what happens. First C loads Class Worker. Next, MyService is loaded by P, and passed Worker. During this instantiation and while the constructor is executing, MyService needs to load up AbstractWorker (recall that the Sun JVM performs lazy loading of Class definitions). Here, since MyService was loaded by P, when AbstractWorker needs to be loaded, it asks P to load it. Here we have two more situations:

  1. 2.0 P loads AbstractWorker
  2. 2.1 C loads AbstractWorker

In situation 2.0, P loads AbstractWorker, which makes MyService fully functional because it has all the Classes it needs. In situation 2.1, P still cannot load AbstractWorker and we are stuck in the same situation where P will always error out when it attempts to use AbstractWorker. In this new situation the error will occur when the MyService is initialized. The important point is that situation 2.0 works fine when P attempts to load the AbstractWorker Class definition.

Now what happens when the Client starts the MyService thread is that the instance of Worker is created by loading the Class definition for Worker using C. Worker extends AbstractWorker, which is all that MyService knows about. When MyService is handed a pointer to Worker it uses it as an AbstractWorker, but the Class that is running is the Worker instance. This is the crux of ClassLoader usage. Since Worker was already loaded, it doesn’t matter that it was loaded by another ClassLoader, MyService is still free to makes calls to Worker via its super-class AbstractWorker.

This illustrates that instances of Objects aren’t ClassLoader bound, while the Class deinitions are. Instances are free to roam about the JVM across Thread boundaries and to Classes loaded by any ClassLoader as long as the Class definitions of the Object instances are either known by the ClassLoader in question (situation 1, 3 and 4) or known via a super-class or interface (situation 2.0). In all other cases, the ClassLoader does not have enough information at at runtime to completely setup the Class definition and therefore will failed at runtime, usually with a ClassNotFoundException.