Tuesday, March 24, 2009

I am Visible but am I Accessible?

During the JSR 294 Expert Groupt meeting this Monday, we fell in to a long conversation about the distinction between visibility and accessibility in Java. This is an important distinction as we work on modularity for Java.

Visibility is whether one type can see another type. In the JLS, this is discussed as observability. In the JVMS, this is about class loading. Basically, this can be described as whether type T is visible to type S. At compile time, this means that the compiler can locate type T when compiling type S. At runtime, this means that the class loader for type S can load (either directly or through delegation) type T. A type can also be visible through reflection. Even if the class loader of type S cannot load type T, type S may come across type T while reflecting. For example, an object may be of type T even though type S directly refers to it via an interface type I.

Accessibility is whether one type can access another type or a member of another type. This is discussed in the JLS and the JVMS. Most people know accessibility by the public, protected, and private keywords. Also see AccessibleObject.

Visibility and accessibility interact, but they are discrete concepts that must be understood separately as we work on modularity for Java. First a type must be visible in order to use it. Then the type must be accessible or the interesting member of the type must be accessible. It is possible for a type to be visible but not accessible.

OSGi provides it modularity though restricting visibility. This makes sense since OSGi is built on the ClassLoader model. So if bundle A imports packages which are exported by bundle B, bundle A's class loader will not have visibility to any other package in bundle B. But if bundle B registers a service implemented by a type which is not visible to the class loader of bundle A, bundle A can still get the class object of the service (e.g. service.getClass()). If that class has public methods which are not part of the service interface, bundle A is able to call them.

Adding a module accessibility keyword to Java will allow the VM to enforce access control when access is attempted across a module boundary. So in the example above, if bundle A and B are in different modules (as to-be-defined by JSR 294) bundle A cannot access the module accessible member of the service implementation class from bundle B. This would give bundle authors more control and encapsulation.

The difficult part is to define the module boundary so the VM can enforce access and this is still an area of ongoing discussion in the JSR 294 EG. Related to this is also the desire to have Java compilers begin to understand module boundaries with respect to visibility and also the new module accessibility keyword. javac currently has a simplistic view of visibility: -classpath/-sourcepath. This has none of the restricted visibility of a current module system like OSGi. How to enable java compilers to have visibilty which better matches the runtime will be a major challenge.

[2013-10-14 - Updated links to fix link rot from Oracle acquisition of Sun.]