Closing the closed APIs
By Erik Costlow-Oracle on Dec 12, 2013
Earlier this year, Wired published an article stating that, “Oracle has actually opened up Java even more — getting rid of some of the closed-door machinations that used to be part of the Java standards-making process.” This openness comes through OpenJDK and the Java Community Process, where different companies and developers all work together to guide the future of the Java Platform.
Part of opening Java involves dealing with the evolution of internal APIs in the JDK outside the actual Java Language specification and APIs. While developers should not be using internal APIs like sun.* packages, over the course of Java’s 18 year history, various applications have at times used these APIs for different reasons. Use of these implementation-specific, internal APIs poses challenges when they change and may decrease an application’s portability between different Java implementations . Given the ease of obtaining component libraries, we are looking at ways of identifying and mitigating usage of internal APIs in favor of APIs intended for public use.
I will cover several topics in dealing with these internal APIs:
- Approach in identifying internal APIs
- Current target: CORBA and Applets/SecurityManager
- JDeps in Detail
Approach in identifying internal APIs
The definition of “internal API” is any package or class provided by a Java implementation that is not in the public API set. Gearing up for JDK8, OpenJDK contains a new tool called JDeps that is able to locate use of internal APIs within an application’s JAR files or bytecode. By running this tool, you can see which components use internal APIs and which internal APIs they use.
We have run JDeps against a number of applications to figure out popularity of internal APIs and understand any impact.
CORBA and Applets/SecurityManager
Starting in Java 7 update 51 (January 2014), we will move the internal undocumented com.sun.corba.se APIs into a restricted API list. This will affect applications only if they do all of three things:
- If your application uses restricted permissions (i.e. sandboxed RIA or runs with a SecurityManager)
- AND uses CORBA
- AND uses undocumented internal Sun APIs (com.sun.corba.se.*) to do it.
The first attempt at moving internal com.sun.corba.se APIs into a restricted API list came back in June of this year on the OpenJDK mailing list. After more reviews, a better patch was created in October. Beginning with Java 7 update 51, the internal CORBA APIs are entering into a restricted API list. This means that if you have an RIA using this internal API, your application will need the manifest entry "Permissions: all-permissions" and cannot use the sandbox. If your application specifies fine-grained permissions through the SecurityManager, then you will need the "accessClassInPackage.com.sun.corba.se" permission.
- To see if your code or components use these internal CORBAP APIs, use JDeps and search the output for "com.sun.corba.se"
- If the above JDeps output says that you are using the undocumented internal APIs, you have two options:
- Recommended: Update the code to use javax.rmi.CORBA or org.omg.* APIs instead of the otherwise undocumented internal APIs.
- Bide time by either using “Permissions: all-permissions” manifest entry in your applet or obtaining the "accessClassInPackage.com.sun.corba.se" permission from your SecurityManager. Please use any time gained to work on Option A, above.
JDeps in detail
OpenJDK 8 introduces a utility called JDeps that looks through JAR files and identifies which JAR files use internal APIs and then lists those APIs. This answers the questions, “am I using these internal classes” and “if so, which ones.” To use JDeps and check your applications, just download a preview release of JDK8. You do not need to actually test or run your application on JDK8, this just happens to be where the JDeps utility is.
You can then run JDeps on an application even if you do not have the source code.
To run JDeps against an application, the command looks like:
jdk8/bin/jdeps -P -jdkinternals *.jar > your-application.jdeps.txt
The output inside your-application.jdeps.txt will look like:
your.package (Filename.jar) -> com.sun.corba.se JDK internal API (rt.jar)