Add the sun-provided platform specefic extensions to the apple-provided JDK source jar
The problem
The apple-provided JDK for mac osx systems, i.e. the developer version source JAR file doesn't contain the required sources for the platform-specific extensions provided by sun. When inspecting or
debugging the JDK code via an IDE then that will result in displaying the decompiled version of these classes instead of the actual sources that should be shipped with the JDK distribution.
However, the same sources for these extenstion packages (sun.*) are available from within the OpenJDK6, all what we need to do is to download/clone a copy of the OpenJDK6 sources and copy these
over to the apple-provided JDK source JAR file to have the actual sources being displayed in your IDE while inspecting/debugging code.
How to do it?
Navigate to the home directory where your apple-provided JDK is installed, you can do so using the following command:
cd `java_home -v 1.6`
Rename the original source JAR file that contains the source codes missing the sun.* platform extension packages, you can do so using the following command:
sudo mv src.jar src.jar.orig
Check out the latest copy of the OpenJDK6 sources, you can obtain a copy of the OpenJDK6 sources either from a ZIP file or via clonning a Mercurial repository, here we we will
clone the latest copy from a Mercurial repository using the following command:
hg clone http://hg.openjdk.java.net/jdk6/jdk6/
Now we need to make a copy of the original source JAR provided by apple and extract it, later on we will add the missing sources into it before copying back into our JAVA_HOME directory
cp src.jar.orig ~/tmp
cd ~/tmp
jar -xvf src.jar.orig
Now we need to copy the missing sun packages from the OpenJDK sources into the content of the extracted jar, as follows:
cp -R >The directory to your OpenJDK6 sources>/jdk/src/share/sun .
After copying the missing sources we need to re-build the sources jar and move it back again into the JAVA_HOME where the apple-provided JDK is installed, we need to also make sure to restart
our IDE after copying the new JAR for the changes to take effect.
jar -cvf src.jar *
sudo cp src.jar `java_home -v 1.6`
Java OpenJDK is an attempt to have all the development for the reference implementation of the java platform being done in the open and to create a community around the development process comprised from the day to day working Java developers which would help to have better standard, a user-targeted API and an early feedback of usability and ease of use fed into the JDK community.
It will also allow the day to day developer to interact and hack with the OpenJDK as its being developed day after the other. The current release of the OpenJDK is the JDK8. The sources of the open JDK is being hosted on a Mercurial repository and it is publicly available for download.
Cloning the JDK repository is done on a read-only Mercurial repository, while writing (committing changes) is done on a read-write repository called the gate repository. Changes are autmatically pushed from the gate to the read-only repository. Each JDK release consists of multiple projects, each project has several components (or repositories). The collection of repositories a project comprised of is called a forest. As such, its advisable to clone the whole set of JDK forest when working on a particular project rather than a single project's repository for the sake consistency.
The naming scheme that the JDK repository follow is as below:
release/project{-gate}?/component
This article is aimed to be a simple step by step guide to build the OpenJDK8 on Mac OSX systems with a little insight on the build process tools and techniques
Prerequisites
The following is a list of the required software and tools for building the OpenJDK
Mac OSX 10.7.3 or later
Having the latest version of Xcode installed on your mac along with the developer tools. On my machine, I had the 4.3.2 version installed.
Since the JDK source code is hosted on Mercurial repository, we need to have the hg Mercurial tool installed, the required version should be 0.9.4 or newer, on my machine I had the 2.2.2 version installed.(to know which version of hg installed on your system, run the following command: hg -version)
An earlier version of the JDK, preferably JDK7.
Build instructions
install the bootstrap JDK:
The OpenJDK build process requires the existence of an earlier version of the JDK to be used as the bootstrap JDK during the build. The preferred version of the JDK to be used as a bootstrap JDK is the JDK7, but an earlier version such as JDK6 should suffice. To make sure that you have the latest version of JDK installed, run the following command:
The build process requires that we unset the JAVA_HOME directory from the shell within which we are running the JDK build process, to do that run the following command:
unset JAVA_HOME
set the ALT_BOOTDIR:
At this point we need to set the ALT_BOOTDIR environment variable to point to the version of the JDK that we like to use as the bootstrap JDK:
Now it's time to download (or clone) the latest sources of the OpenJDK from the Mercurial repository, for that we need to use the hg command as follows to download the top level projects that the JDK is comprised of, but this will not clone the nested repositories contained in each project:
hg clone http://hg.openjdk.java.net/jdk8/jdk8
Clone the nested repositories:
Now we need to clone all the nested repositories within the JDK, for that we need to run the get_source.sh shell script as follows:
chmod u+x get_source.sh # adding the execute permission ./get_source.sh
On my machine it took approximately 25 minutes to download the whole source code of all the open JDK repositories from the Mercurial repos, and the whole size of the JDK sources is about 735 MB
pull the latest updates:
in the case that we are building from an out of date clone of the JDK sources, then we need to pull the latest updates before attempting to build it, while we can do that using the Mercurial command line but it will be tedious to do that for every single nested repo, hence we have a helper script that can do that for us in one go:
sh ./make/scripts/hgforest.sh pull -u
Build the JDK
Now it is the time to start building the OpenJDK, the build is managed using the GNU make as follows:
chmod u+x configure # Adding the execute permission to the current user
./configure # Running the configure script
make sanity # run the sanity checks
make # Start the actual build, this will also run the sanity checks
install the newly built JDK:
Now the build process has been completed, its time to move the newly built JDK bundle into the JavaVirtualMachines directory:
cd ./build/macosx-x86_64/j2sdk-bundle
sudo cp -R jdk1.8.0.jdk /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk
to switch to the newly created JVM, you can set your /usr/libexec/java_home environment variable to the directory where the new JVM has been installed:
Note: The xcodebuild shell script on Mac systems is used to run the xcodebuild() tool using a version of the Xcode developer tool installed on your machine, this script is a wrapper script that is used to run different versions of the xcodebuild basing on the developer tools path settings that can be located and changed using the xcode-select tool, if you happen to upgrade to a newer version of Xcode tools then that path might get reset and cause the xcodebuild to complain about not being able to locate the right directory to run the Xcode utility from which would cause your build to fail, here is how you can set it to the right path and resume the build:
xcode-select -switch e.g. /Applications/Xcode.app/Contents/Developer
to make sure that you have the right path for the Xcode developer tools set, run the following command:
xcode-select --print-path
Sunday 11 March 2012
An Introduction into the concept of nested classes in Java
Overview
This article is going to shed some lights on the concepts of the implementation of the nested classes in Java in a simple and easy to comprehend manner. The various types of nested classes are explained with some examples that explain their usage and advantage over normal top-level-classes.
Concepts
One of the nice and highly advantageous features of Java is the ability to define nested classes, i.e. classes within classes. In java classes are either top-level-classes (classed defined directly within a package) or nested classes (classes defined within top-level-classes). One might wonder in regard to why all this complication is even helpful, and whether or not such classes bring any advantage to the java programmers at all.
Well, during the time I’ve spent exploring the what’s ad why’s of Java’s nested classes, I’ve realized two important, but distinct, advantages to that, and these are:
Having the ability to define nested classes will help grouping the related functionality together, imagine the case in which a certain class is being used only once from within another class, then there is no obvious need to add a clutter to the enclosing package by defining a top-level-class that will merely be used by only one another class. Thus, having that functionality contained within a a nested class increase readability and reduce clutter.
Another very important advantage of having nested classes is the fact that nested classes will be able to access all the class members of their enclosing top-level-class (including the private member methods and variables), this is a more efficient way than the traditional way of accessing the non-private members using an object instance and a noticeable advantage of this feature can be seen when developing event-based applications where action and event listeners can be defined as nested classes rather than having them as separate individual top-level-classes
A difference or may be an advantage nested classes posses over subclasses (as one might think, why not simply define subclasses instead of nested classes) is that subclasses can’t access private members (unless they are declared as protected) while nested classes can.
Nested classes types and basic examples
Nested classes in java can be classified into the following types, each exhibit a slightly different behaviors than each other, which might limit their use to a specific particular case:
non-static nested classes: Non static nested classes are defined within the top-level-classes and they are bound by the scope of their enclosing class, non-static nested classes can have direct access into all of the members (event the private ones) of their enclosing class, on the other hand, the enclosing class doesn’t have any access to the members of the enclosed nested class. It is also worth to mention that nested classes (in general) can be defined from within any block inside a top-level-class, that’s could be a method block or even a control statement target block (such as if, for or while). There are two flavors of non-static nested classes, and these are:
Inner Classes: These are the most widely used type of nested classes, the following code excerpt shows how to define a an inner class within a normal top-level-class, how easily the private members of the enclosing class can be accessed by the nested class and how to obtain an instance of the inner class from within the enclosing class:
public class OuterClass
{
private int private_member_variable = 100;
public class InnerClass
{
public void printPrivateVariable()
{
System.out.println(private_member_variable);
}
}
public void callInnerClassMethod()
{
InnerClass innerClass = new InnerClass();
innerClass.printPrivateVariable();
}
public static void main(String args[])
{
OuterClass outerClass = new OuterClass();
outerClass.callInnerClassMethod();
}
}
It is very important to state that the instance of the Inner class doesn’t exist in isolation, rather it is bounded by and associated with an instance of their enclosing top-level-class, and this impose a slight restriction on the inner nested classes which is that they can’t have any static members that normal top-level and static nested classes can. the following code excerpt depicts that concept and how an instance of the Inner class can be obtained from code outside their enclosing class:
public class TestClass
{
public static void main(String args[])
{
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.printPrivateVariable();
}
}
Anonymous Classes: Java supports the definition of un-named inner classes, these classes differ from the inner classes in only one thing, which is that they are un-named, hence came the name “anonymous”. Anonymous classes can have direct access to all of the class members of the top-level-class in which they are defined.
The following code excerpt shows how to define anonymous classes from within top-level-classes:
public class Test
{
public static void main(String args[])
{
Runnable runnable = new Runnable()
{
public void run()
{
}
};
}
}
Anonymous inner classes come in handy when an object instance are required on the fly that extends a certain class or implement a certain interface without the need to write a complete top-level-class for that. The situations where anonymous inner classes are beneficial can be envisaged when the need arise for a Runnable class to be passed to a Thread (as the above code excerpt shows) or when an event listener implementation need to be passed to register for certain event occurrence in event-driven development environments. The syntax for defining anonymous inner classes can be broken down into the following:
new Interface to implement | abstract/concrete class to extend () {body of the anonymous class to be defined};
static nested classes: Static nested classes exist in isolation from within the top-level-class that they are defined within. On the contrary to the non-static nested classes, static nested classes can’t directly access the members of the class that they are defined in (simply because they are static members, and in static class members can only access other static members directly), but they can do so using an object instance of the enclosing top-level-class. The following code excerpt shows how static nested classes are defined, how they access the the private members of their enclosing class (only via the use of an object instance) and how to obtain an instance a static nested class:
public class OuterClass
{
private int private_member_variable = 100;
public static class StaticInnerClass
{
public void printPrivateVariables()
{
OuterClass outerClass = new OuterClass();
System.out.println(outerClass.private_member_variable);
}
}
public static void main(String args[])
{
StaticInnerClass staticInnerClass = new StaticInnerClass();
staticInnerClass.printPrivateVariables();
}
}
To obtain an instance of a static nested class from within code defined outside the enclosing class, one needs to follow the normal instance creation mechanism in java as the static class exist in isolation from their enclosing class and they are not associated with any instance of their enclosing class:
public class Test
{
public static void main(String args[])
{
OuterClass.StaticInnerClass staticInnerClass = new OuterClass.StaticInnerClass();
staticInnerClass.printPrivateVariables();
}
}