<B>Prepared by Chris Bergstresser ( <external mailto:chris@subtlety.com>mailto:chris@subtlety.com</external> ) Version 0.1 28 Oct 1997
In the design and deployment of object-oriented systems, versioning is a critical requirement. This document attempts to briefly describe the problems associated with versioning for Java, explain what API's Sun is creating to help solve the problem, and propose a workable system for JOS.
There are a number of problems associated with deploying programs which rely on a set of heterogeneous components external to the program. These include:
A new version of a class may be Incompatible with previous versions. Software designed to run with one class may behave erratically when used with a later version.
Newer systems may rely on a set of classes which are outdated on the target system. Thus, the installation of a single component may require the updating of any number of other components.
In a distributed environment, it is possible that some systems may be using old versions of a class, and may continue to use the old version while interacting with newer versions on other computers. Indeed, it is possible (in fact, likely) that within the same system a given program may have some classes loaded in a classloader or serialized to disk while the source for the class is changed.
A more detailed examination of the problem, as well as Sun's pre-release specification, can be found at http://java.sun.com/products/jdk/1.2/docs/guide/versioning/spec/VersioningTOC.doc.html
Sun has recognized the problems with distributed systems, and is publishing a versioning specification for inclusion with a later version of Java.
The basic unit of distribution for Sun is the package. All the classes in a given package are distributed in bulk. There is no provision made for updating individual classes within a package.
Packages distributed in an archive must report their versioning information through the manifest file. This file contains information about the Title, Version Number, and Vendor for both the implementation which is being distributed as well as the specification which the implementation adheres to.
The classloader is responsible for tracking the versions of packages currently loaded, for use in debugging.
Sun's versioning API makes the assumption that all changes to a specification are backwardly compatible. All serializable classes must insure they can deserialize and be deserialized by older versions. Interfaces are not permitted to add, change, or remove methods. Classes are not permitted to remove or alter existing methods. Sun's versioning specification provides no way to indicate that a given package is incompatible with a previous one.
JOS should use Sun's definition of a package as the minimal unit of distribution. Exceptions will be made for "packageless" classes -- factory objects, small utility classes, and drivers which do not make sense as a part of a larger distribution. The classloader should track these pieces individually.
When a set of classes is upgraded, the new classes will be copied to the local system. The old classes, which are to be replaced, are not removed. Instead, packages already loaded in classloaders will still exist, and will continue to do so for as long as a class remains loaded in memory. Once all of the classes in an upgraded package has been unloaded, the next loading of a class from the package will use the new version. The system is free to erase the previous package. If the package in question is a system-wide package, replacement will require a reboot. For packages loaded locally to a process, this can be an incremental process; new processes can use the new classes, while old processes can continue using the old. As long as Sun's compatibility rules are followed, there should be no problems with this model.
It may be desirible to install two different versions of the same package on the system. This can be accomplished by having the classloaders for different processes refer to the different versions, thus preventing them from being loaded into the same space. This causes a problem from two points-of-view. First, it requires a knowledgeable administrator to actively track down the incompatibilities and specify which processes should use which versions. Second, this will not work for system-level packages, since they must be shared among all processes (and as such, cannot use different versions).
There should probably be a mechanism in place where, once a given package is upgraded, the previous version can be recovered and reinstalled if the new one turns out to be unworkable. Suggestions?
System packages are defined as those packages which are shared among all classloaders. Obviously (or not?), the jos.* packages would fit into this catagory. Individual user's classes would not (or would they?). The question is mostly whether the java.* packages should be, or should not be, or whether this should be user-configurable or not. This has an effect on other portions of JOS -- for every package that is not shared, a separate copy must be kept in memory for each classloader that references it.
It might be possible to define an intermediate level of sharing -- a class is shared among all the user's processes, but not system wide. This would cut down on memory use, but greatly increases the difficulty managing upgrades.
How much faith do we give Sun's versioning spec? How likely is it that incompatible versions will surface, and (more to-the-point) that we will need to run incompatible versions of packages side-by-side in the same system? The answer to this question determines how much effort we need to put into the above. Obviously, if there is no need to run incompatible versions in JOS, things become much easier.
java.*
;
java.
, too; and should have named it java.11.
.
java.
, too; and should have named it java.12.
;
jos.10.*
jos.20.*
jos.53.*
org.jos
.
org.jos.core1a
, org.jos.core1b
, and org.jos.core1c
;
org.jos.io1a
, org.jos.io1b
, and org.jos.io1c
;
org.jos.app1a
, org.jos.app1b
, and org.jos.app1c
; and
org.jos.awt1a
, org.jos.awt1b
, and org.jos.awt1c
.