C# introduced the
internal keyword to enables information hiding across program boundaries. It can improve the ease of maintenance on much larger programs. When a public class is declared as internal, it’s accessible from the assembly containing this class, but hidden from any other assembly using it.
Java doesn’t have an equivalent of the internal keyword, and not provides any solution out of the box to have the same behavior.
Let’s declare a class
Test like this:
Test is visible inside the package but not outside it, and if we declare
Test as public, it will be visible from any class inside or outside the jar.
What’s the solution we have to make the class test visible inside the jar and hidden from any other jar?
1. Naming convention
The method most used to inform that some classes are internals is to put them inside a package named internal, for example here are all internal packages from the hibernate core jar.
With this solution we inform the library user that these classes are internals, but they can be instantiated from other jars.
2. Custom class loader
To resolve the issue of the first alternative, we have to not accept the instantiation of classes inside internal package, for that we have to know how they are instantiated.
The Java Classloader is a part of the Java Runtime Environment that dynamically loads Java classes into the Java Virtual Machine. Usually classes are only loaded on demand.
It is the class responsible for finding and loading class files at run time. Creating your own ClassLoader lets you customize the JVM in useful and interesting ways, allowing you to completely redefine how class files are brought into the system.
To have more control over class instantiation, we can create our own class loader and add a custom logic. And in this case we can refuse the creation of a specific class if it’s inside an internal package. And to use our custom class loader the
setContextClassLoader method is invoked.
We can improve this solution by defining an internal annotation instead of checking the package name, for example we can declare an internal class like this:
public class InternalClass
And the custom class loader check if a class is tagged as internal. But its not perfect yet, the drawback of this solution is that the using of internal class is detected at runtime and not when compiling the code, refusing the creation of internal class could create problems in production
environment. To avoid this behavior we can only log a warning instead of refusing the creation.
And to check the not using of internal classes at the development level, we can use JArchitect and create a
custom CQLinq query like this:
from t in Types where
t.TypesUsingMe.Where(a=>a.ParentProject!=t.ParentProject).Count()>0 && t.HasAnnotation("internal")
What’s interesting with the custom class loader solution is that we can restrict a package to use only some specified packages.
3. External Framework
OSGi became very popular today, thanks to its modularity approach and its capability to enforce logical boundaries between modules. OSGI is an example of framework using a custom class loader to define many rules related to visibility and accessibility between packages and jars.
OSGI give us many possibilities to define logical boundaries and emulate the internal behavior, here’s a post describing the OSGI framework.
4)Wait for java 9
Java 9 will come with jigsaw another alternative to OSGI to simplify modular
programming, and in this case the JRE class loader is modified to restrict the creation
of classes depending on configuration files defining the boundaries. This post
describe the jigsaw alternative.