Java and security bits
Superpackages in JSR 294
The Java language modularity concepts proposed by JSR 294 have recently attracted some attention. I will attempt to clear up a few misconceptions and clarify the relationship of JSR 294 development time superpackages with JSR 277 deployment modules.
The basic ideas are described in the JSR proposal and Gilad's blog entry. Although these pages do not go into much detail, they capture the underlying concepts very well and I encourage you to read them. I will try to explain the background and fill in some of the blanks. Let me stress that this is just the initial proposal and as always the actual specification will be the result of the expert group discussion and may end up looking differently.
Background
JSR 294 deals with information hiding. Information hiding refers to the practice of keeping implementation details concealed while allowing access to published APIs. This prevents consumers from relying on implementation internals and makes it possible to change aspects of the implementation without affecting consumers.
In Java, we achieve information hiding by declaring types
(classes and interfaces), methods, and fields with non-public access modifiers. For example, a class with default access
(aka package private) or a private method. The access control rules are defined in the
JLS
and
JVMS
and are enforced by javac at compile time and the virtual machine at runtime. These low level mechanisms are very reliable and also serve as the foundation of Java platform security.
All this works fine as long as a project fits into a single package. Once the project grows beyond that, you may find yourself forced to make implementation classes public in order to access them from multiple packages in the project. That loses the benefits of information hiding, which is clearly suboptimal and a long-standing complaint that often comes up in language discussions in forums such as JavaOne.
Goals
When we decided to address these issues, we had the following goals in mind:
- extend the access control model defined by the JLS and JVMS to accomodate projects larger than a single Java package
- the extensions to the access control mechanisms should be simple and consistent with the existing model
- access control information should be declared in Java source files so it can be processed and enforced by javac.
- enable the new model to serve as the basis for deployment modules, but it should also be usable on its own without requiring modifications to the deployment mechanisms.
Proposal
The solution is a new entity tentatively called superpackage. A superpackage can be thought of as a named collection of types from one or more packages. Public types can be declared as exported to make them accessible outside the superpackage. Public types in a superpackage that are not exported are accessible only to other types in the superpackage.
Unlike packages, superpackages are explicitly declared in a
Java source file. They are compiled by javac into
a .module file (cf. class file).
At runtime, the module file is loaded by the VM, which uses
it to enforce access control. It is also reified via a reflective API similar to java.lang.Class.
As a rough analogy, you could think of a superpackage as a grouping of related packages similar to how a package is a grouping of related classes. Where today classes have either public or default (package private) access, for code that uses superpackages there will be exported public, non-exported public ("superpackage private"), and default (package private) access levels.
For practical purposes, attempting to access a non-exported class from outside its defining superpackage will result in the same behavior that is observed today when attempting to access a package private class from outside its defining package.
Deployment modules
JSR 294 deals with modularity at the Java language level. Deploying a module also requires consideration of aspects such as class loading, versioning, and packaging formats. Those issues are the topic of the deployment modules defined by JSR 277. That project uses the foundations provided by superpackages to build a system with the desired runtime semantics.
The reason that the development and deployment aspects are handled by two separate JSRs is rather simple: they are dealing with two different sets of problems. For example, the Java source language should not define the JAR file format and a set of libraries should not define VM level access control rules.
There are interactions between development and deployment, but to a large extent we are talking about independent issues. A divide-and-conquer approach that enables focused expert groups to concentrate on their individual problem space is preferable to a single large project. Of course, we want to coordinate between the development and deployment solutions, which is why both expert groups have several members in common.
Q&A
Do JSR 294 superpackages require deployment via JSR 277 modules?
No. Superpackages are independent of the deployment mechanism. They can be deployed in regular JAR files loaded by an existing ClassLoader such as a URLClassLoader, as a JSR 277 module, or using other mechanisms. In all cases the superpackage access control mechanisms are enforced by the Java VM. But the advanced deployment features of JSR 277 are only available if you package and deploy the superpackage as a JSR 277 module.
Why enforce access control at the VM level rather than hide implementation classes via some filtering mechanism in the ClassLoader?
The existing Java access control mechanisms operate at the VM level. That architecture has proved to be reliable and secure. Pushing access control decisions to a ClassLoader is inconsistent with that model. It is also susceptible to incorrect ClassLoader implementations and programming errors leading to accidental disclosure of ClassLoader objects. A deployment module system might still want to hide classes at the ClassLoader level, but the fundamental access control decisions must be made by the VM.
Why does the
.modulefile list all the member and exported types?
An authoritative membership and export list is necessary for access control enforcement. It also eliminates the reliance on packaging provisions such as package sealing that are currently required for correctness in some configurations.
Can a class be a member of more than one superpackage?
No. Just like a class can only be a member of one package, it can also only be a member of one superpackage. At deployment time, an exported class can certainly be accessed from multiple contexts by setting up the ClassLoaders appropriately, but that is unrelated to development time concepts.
What about separate compilation, which is another area mentioned in the JSR 294 submission?
That is a separate topic that we should discuss another time. Stay tuned.
PS: don't let recent history fool you into believing that I will be posting an entry every day ;-) Most times it will be more like 2 or 3 entries a month.
Posted at 15:27 Nov 08, 2006 by Andreas Sterbenz in Modularity | Comments[4]
Posted by Danny Coward on November 09, 2006 at 11:34 AM PST #
Danny, good point. We certainly plan to have javadoc take advantage of superpackages. We have not really discussed that yet, but there are a few obvious things we could do, such as grouping per superpackage, and hiding non-exported classes by default (similar to package private classes today).
Posted by Andreas Sterbenz on November 09, 2006 at 04:22 PM PST #
Posted by Glyn Normington on November 20, 2006 at 01:45 AM PST #
Glyn, we are looking at how to best make the expert group discussions more transparent to the community. What you suggest is one of the main options we are looking at. I will post the details once they have been worked out.
Posted by Andreas Sterbenz on November 22, 2006 at 05:01 PM PST #