Search This Blog

Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Wednesday, May 9, 2012

Differences in Creating a Servlet in versions 2.5 and 3.0 Of the Servlet Spec.

Differences in Servlet Definitions between v2.5 and v3.0

The following 2 examples show the difference between how a Servlet Java Class and associated web.xml deployment descriptor was changed in the upgrade from version 2.5 to version 3.0 of the Servlet Specification. I found this a simple and interesting look at the way the definition of a Servlet in code has now been simplified through the use of annotations from JSR 175.

2.5 Version of Servlet Definition 

Java Class Of Servlet in 2.5

public class MyServlet extends HttpServlet {
    public void doGet (HttpServletRequest req, HttpServletResponse res) {
        ....
    }
}

Deployment descriptor in 2.5 (web.xml)

<web-app>
    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>samples.MyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/MyApp</url-pattern>
    </servlet-mapping>
    ...
</web-app>

3.0 Version of Servlet Definition 

Here is the much simplified version written to the Servlet 3.0 API. As MyServlet is annotated as a servlet using the @Servlet annotation, it gets initialized during the start-up of the web container. Note that the deployment descriptor is optional in this case.

Java Class Of Servlet in 3.0

@Servlet(urlMappings={"/MyApp"})
public class MyServlet {
    @GET
    public void handleGet(HttpServletRequest req, HttpServletResponse res) {
        ....
    }
}

Deployment descriptor in 3.0 (web.xml) - Optional


Saturday, July 30, 2011

Java JDK 7 - Finally Released

JDK 7 Released ... Finally!!!

A Detailed Overview Of New Features/Functionality in JDK7

 

Introduction

The following long-ish blog entry is a relatively detailed overview of information for the JDK 7 Release of 29th July 2011 by Oracle. Given the release has just occurred I have collected a large amount of relatively detailed information regarding the JDK7 release that developers looking to upgrade from Java 1.6.0_26 to JDK7 will find useful. This information includes a general overview of the entire release with access via links to the various documentation you may need, release notes, installation instructions, JavaDoc API's etc., as well as changes that have been included and whether they have caused compatability and generally known issues that you may encounter.  

More importantly for most people that will find their way here Ive also included information about the Programming Language enhancements (these are the ones that if you've heard anything about Java 7 you would've heard about these) and include the various Project Coin upgrades, and new functionality like try-with-resources, multi-catch, Strings in switch statements, upgrades to numeric and binary literals, etc. Besides these Ive also included other enhancements that generally you are less likely to hear about as they arent discussed as often as they arent focussed at the programming language level per-se but can include things like JVM, Garbage Collector and various new Framework (fork./join, NIO2, etc) inclusions and improvements.  If your primarily after this information which I think most people interested in Java 7 will be and you want to bypass the sections on JDK7 Release History, Release Notes and various JDK 7 Documentation, then simply skip ahead to the two sections on enhancements further down towards the end of this blog entry under the main title 'Overview of JDK 7 New Features' and each labelled with their respective titles:
  • General Enhancements in the Java JDK 7
  • Programming Language Enhancements in Java SE 7
Since a lot of this information is already accessible and has been provided by the implementers (Sun/Oracle) rather than copy/paste large slabs of text or re-write it myself with new examples etc., Ive focussed more on providing a brief introduction and over-view in all these cases and then providing a series of links to much more detailed information in the form of tutorials, explanations and specifications. The general idea of this blog entry is to provide a single point of entry for any and all information regarding Java 7 and to be able to get some initial info on what it is that your interested in before being re-directed to much more detailed information via outgoing links. Lets see how I do hey :-)!
 

Overview Of JDK7 Release History

So after almost 5 years (four years, seven months, and seventeen days) since JDK 6 and after 9,494 bug fixes, 1,966 enhancements, 9,018 changesets, 147 builds, and four JSRs, JDK 7 is done (Thanks Mark Reinhold for that info: http://mreinhold.org/blog/jdk7-ga).  Oracle announced the release of JDK 7 today (2011-07-29) which interestingly followed the scheduled release plan exactly which is reassuring to see for the future JDK8 release as it raises my level of trust that if they say they'll release JDK8 in 2012 that it'll actually happen unlike JDK7 which as we know see was delayed over and over for 5 years:

    http://openjdk.java.net/projects/jdk7/

The plan above was made up of 147 builds as mentioned comprising a total of 13 Milestones. Information on each of the milestones with further detailed information aboutwhat a particular feature in a milestone entails, along with a detailed calendar of build dates and milestones (for those interested in such things) is provided in the following two links:

Overview Of Release Notes

The next link below is the main download page:


This page has downloads for both the previous version of JDK6 (1.6.0_26) as well as everything related to the new JDK7 release (ie: JDK7 with EE, JDK7 with Netbeans 7.0). Incidentally Netbeans 7.0 is a version of Netbeans that is already built to work with JDK7.0 so you can start using JDK7 with the Netbeans IDE straight away and get access to the cool features within the IDE (ie: the Project Coin features are useable and visible in the IDE and it gives correct information and code-completion for them already, which as I say is nifty and great that its available so early on the same day as the JDK 7 release itself).

The index page for the Release Notes of JDK7 are at: 

These are detailed and include various documents. The first of these Ill look at is the Java SE 7 Features and Enhancments page located at:


Since this is a major feature release this link includes information on the various features and enhancements in Java SE 7 and JDK 7. The beginning of the document above has a number of sections that highlight the Technology Changes as well as the various RFE (Requests For Enhancements) that were addressed. You can follow these links for more detailed information and I suggest doing so. Furthermore one of the last sections is a list of the known issues which Im linking to below as this is an important section of information. Skimming through this section there are a number of known issues in this release which its important to be aware of. One are where there seems to be a number of issues in is the use of Genereics and how Re-ification of Generics affects the type of code that can and can't be written. I found these useful to skim through simply to be aware of what can occur and when writing code I'll now be aware of what to look out for. See link for known issues:

The Release Notes also provide info on compatability. Much like the known issues section this is also useful to read through to be aware of problems that may arise during upgrade from JDK6 to JDK7.  Although in general and despite the introduction of a number of new features (which JDK6 didnt have compared to JDK5) the upgrade from 6 to 7 is actually quite painless. The list of compatability issues in the link below is quite small and limited to very specific cases. Though still usefull to read through I would recommend upgrade to 7 as soon as possible as these few very specific cases can a) be dealt with should they arise and b) the benefits from the new features more than out weigh any very minor upgrade problems.

    http://www.oracle.com/technetwork/java/javase/compatibility-417013.html

Again the page above is very well written and the sections on incompatabilities are very detailed indicating which sections of the language are affected (eg: NIO, API, Language, etc):

    http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#incompatibilities

The final parts of the Release Notes are info on a number of sections. These are listed along with their associated links and some short info below along with links to a variety of other docs and information links that are important for the JDK 7 release.

Overview Of JDK 7 Important Documentation and Links

  • Version Numbering and Naming Information - This is information on the various numbering and naming standards used within this release of the JDK. Useful information since Java has an unusual set of naming standards. ie: the version string for the product is reported as "java version 1.7.0_3", the product will be called JDK 7u3, JDK 7 update 3 or, when the update version is not important, JDK 7. http://www.oracle.com/technetwork/java/javase/jdk7-naming-418744.html
  • JDK and JRE 7 Installation Guide - Provides information on performing an installation of each of the modules. If you've ever done a previous install of the Java Platform this is all old hat and Im providing it mainly for completeness sake:  http://download.oracle.com/javase/7/docs/webnotes/install/index.html
  • JDK and JRE 7 README Files - High level README files which provide information on libraries, packages, endorsed override methods, the location of jars and libraries and packages within those libraries etc. 
  • JDK7 Specifications - This page contains links to the Java SE 7 Edition Language and Virtual Machine specifications. It also has archival links to previous specification versions. The specifications are important as they are the final word on how things SHOULD work and I  have often turnesd to them in the past when new versions have come out to see why and how an implementation has been done (ie: previous Java Versions introduced the Integer/Char/Short/Byte internal caches and the specifications provided the final word on initial cache sizes etc). http://download.oracle.com/javase/cmn/spec_index.html
  • JDK7 API Docs - This is one of the critical links and also one of the pieces of documentation any developer will return to time and again. The link is to the root of the java API doco (with new doco for new functionality added in JDK7 labelled using: since 1.7 in the JavaDocs as is standard). http://download.oracle.com/javase/7/docs/api/
  • JDK 7 Tutorials - A set of brand new tutorials has been created with the new functionality added in JDK 7 as a basis and added to the complete existing set of tutorials. All of the tutorials have been updated on the basis of the new release. The new tutorials based on the newly introduced JDK7 functionality are grouped at the start of the page and cover Project Coin functionality amongst other things and so are useful even for experienced Java developers to get a feel for the correct use of new functionality. http://download.oracle.com/javase/tutorial/ 
  • JDK 7 Trouble Shooting Guide - This Java 7 Trouble Shooting Guide contains numerous links to various trouble shooting blogs. Although many of the performance links are JDK6 (since JDK7 has minimal performance features as these are saved for multi-core processing imlementations in JDK8) they ar still valid in the context of this JDK 7 release. http://download.oracle.com/javase/7/docs/webnotes/tsg/index.html
  • JDK7 Documentation Index - This page contains the high-level overview index for all of the API's and various JDK 7 components as well as a section on 'Whats New in JDK7 Documentation' which covers the new features and components which were implemented in this JDK. The first section is a series of tech notes for each section (such as JDBC, JNDI, AWT, Java2D etc.) while the 2nd section gives a good indication of what was added in this JDK release (ie: changes made to the garbage collector, the API's, NIO packages and usage, etc). 

Ive list the changes mentioned in the second section in the final point above in more detail in the following section as these are a good way of seeing whats changed in the JDK for this version.

Overview Of JDK 7 New Features

A good source of an overview for fetaures included in this release is the wiki page (at: http://en.wikipedia.org/wiki/Java_version_history#Java_SE_7_.28July_28.2C_2011.29) and this provides not just the main features but also info on things less well publicised as they are not code features but underlying functionality (such as the info on the XRenderer etc). Another good source of detailed information discussing the various Project Coin features in detail is Oracle's page located at: 


General Enhancements in the Java JDK 7

The enhancements listed here cover the entire JDK 7 release. Actual code/coding enhancements will be listed in the section 'Programming Language Enhancements in Java SE 7' below while here I'll list things like changes to API's, the garbage collector, the JVM, etc.  While the programming language changes have been discussed at length in the leadup to the release of Java 7 the following set of updates and new functionality have in general received less coverage and so are covered at some length here.

Programming Language Enhancements in Java SE 7

The following programming language enhancements and new functionality (as mentioned earlier) have been discussed at some length on blogs etc., prior to the Java 7 release and so here I will cover the new features and aprt from a breif overview provide links to further information.

  • Binary Literals - In Java SE 7, the integral types (byte, short, int, and long) can also be expressed using the binary number system. To specify a binary literal, add the prefix 0b or 0B to the number.
  • Underscores in Numeric Literals - Any number of underscore characters (_) can appear anywhere between digits in a numerical literal. This feature enables you, for example, to separate groups of digits in numeric literals, which can improve the readability of your code.
  • Strings in switch Statements - You can use the String class in the expression of a switch statement.
  • Type Inference for Generic Instance Creation - You can replace the type arguments required to invoke the constructor of a generic class with an empty set of type parameters (<>) as long as the compiler can infer the type arguments from the context. This pair of angle brackets is informally called the diamond.
  • Improved Compiler Warnings and Errors When Using Non-Reifiable Formal Parameters with Varargs Methods - The Java SE 7 complier generates a warning at the declaration site of a varargs method or constructor with a non-reifiable varargs formal parameter. Java SE 7 introduces the compiler option -Xlint:varargs and the annotations @SafeVarargs and @SuppressWarnings({"unchecked", "varargs"}) to supress these warnings.
  • The try-with-resources Statement - The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements the new java.lang.AutoCloseable interface or the java.io.Closeable interface can be used as a resource. The classes java.io.InputStream, OutputStream, Reader, Writer, java.sql.Connection, Statement, and ResultSet have been retrofitted to implement the AutoCloseable interface and can all be used as resources in a try-with-resources statement.
  • Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking - A single catch block can handle more than one type of exception. In addition, the compiler performs more precise analysis of rethrown exceptions than earlier releases of Java SE. This enables you to specify more specific exception types in the throws clause of a method declaration.

The Future .... JDK 8

Although Java 7 has only just been released today the future is coming (some might say its already here), since Java 7 was part of a two pronged strategy undertaken late last year (2010) to ensure a JDK release in 2011 (given that it had been 5 years since releases). With the takeover of Sun by Oracle last year and the Java release having been pushed back several times a proposal was made by Mark Reinhold on his blog  (http://blogs.sun.com/mr/entry/rethinking_jdk7) for one of two options. Push ahead with the current plans for Java and take another 2 or 3 years to the release or trim down the functionality set and aim for a mid-2011 followed by a late-2012 release with the remaining functionality initially proposed for Java 7 to be released in Java 8. The  descision to go with the second option can be seen on Marks blog:

Labelled Plan B it looked roughly like:
  • JDK 7 (minus Lambda, Jigsaw, and part of Project Coin)  Mid 2011
  • JDK 8 (Lambda, Jigsaw, the rest of Project Coin, ++)        Late 2012
A detailed list of functionality for the two JDK's followed:
Along with both a JSR for JDK 8: 
And a set of project pages for each of the JDK 8 features to be implemented still:
So there you have it....JDK 8 and definately stuff to look forward to in that lot, not too mention that there will be multi-core performance improvements made as part of JDK 8 on the non-programming side of things amongst other changes.
Keep watching this space!!!

    Wednesday, October 27, 2010

    JavaDoc CVS Tag Replacements ($Id:, $Revision:, $Date:, $Author:)

    Usage of CVS Keywords in JavaDocs

    In my Java code I use the following tag in all my class level JavaDocs:

    
      /** 
       * Some text describing what this class is for...bla bla bla...
       * @author: mkopka - Marty Kopka - 20101010 - 17:45:23pm
       * @version $Id: $ 
       */
      public class Fubar {   ... snip .. class definition follows in here
    

    ...and then when I commit the code into CVS the $Id: $ tag gets converted into:

    
        ...
        * @version $Id: Fubar.java,v 1.1 2010/10/10 17:50:44 mkopka Exp $
        ... 
    

    Which is all well and good and Ive encouraged all my teams to follow this style as it gets you some bonus information for free basically. You dont need to do anything except put in the initial "Id" tag and then dont touch it from that point on. I'll get updated every commit from that point on and you get the name of the user committing the file, the time and date that they did so and the version in CVS of the current file commit. All good information to have, especially given that you dont have to update it yourself.

    So what am I going to complain about...well nothing actually. I was just going to point out that the string that's substituted into the "Id" tag is actually made of of a number of small parts comprising the larger string. Should you not want all that information (although why you wouldn't I dont know)...but if you dont you can just pick and choose the bits that are good for you. As an example the code below shows the equivalence of the "Id" tag but made up of sub-component like tags.

    
        ...
        * @version $Revision: $ $Date: $ $Author: $ $State: $
        ...
    
    Which will then give: 
     
        ...
        * @version $Revision: 1.1.1.1 $ $Date: 2010/10/10 17:50:44 $ $Author: mkopka $ $State: Exp $
        ...
    

    There's also no reason why ...in theory... you couldn't use these various substitutions inside your code itself (although it would take until a CVS commit before you got any info in it first time around. But I can see a case where a version number for example may be usefully stored in a String and later displayed in the application. Or, seeing as how there is also the possibility to use other tags to substitute in a branch name (amongst other info) you could use that along with version info to provide info to the client. I.e.: something like this I can see as a a possibility:

    
        ...
        String versionAndBranch = "Branch: $: $ Version: $Revision: $";
        ...
        ... snip ... and then at some later date we can use the String above for logging, debugging, display to the client etc.
        ...
        System.out.println("We are using source code from: " + versionAndBranch);
        ...
    

    Now as mentioned, the example above would be empty until you committed the file, but that's not a great problem as normally you would commit the code prior to a production deploy (so the issue would only be in your local development environment). For further info on this I found the following link: http://www.idevelopment.info/data/Programming/change_management/unix_cvs/PROGRAMMING_Using_CVS_Keywords_in_File_Headers.shtml

    Listing of CVS Keywords

    Besides the substitution tags that I listed above there are a number of others that are also available (11 in fact ... or perhaps 12 if you include CVSHeaders from the latest version ... but not all versions have CVSHeaders so be aware of this prior to using it as your version of CVS may not support it). The following listing gives a list of all of the different substitutions available (which I pilfered from an number of different sites and cobbled the info below together. See the end for a listing of http://'s that I used to compile this).

    Keyword Explanation
    $Author: $The user responsible for a change. $Author: markd $
    $Date: $Date and time of the change, in GMT. $Date: 1999/12/23 21:59:22 $
    $Header: $A collection of information: full path to the RCS file, revision number, date/time of last change (GMT), author, state, and locker. (lockers are a rare occurance in CVS)

    $Header: /cvsweb/cvs-guide/keyword.html,v 1.3 1999/12/23 21:59:22 markd Exp $
    $Id: $Like $Header: $, but without the path to the RCS file. $Id: keyword.html,v 1.3 1999/12/23 21:59:22 markd Exp $
    $Log: $
    Inserts the cvs log message. This behaves differently than other tags in that it just inserts new information after the keyword. It doesn't replace the keyword or modify existing text.

    $Log: keyword.html,v $
    Revision 1.3 1999/12/23 21:59:22 markd
    dummy change to bump up revision.

    Revision 1.2 1999/12/23 21:59:15 markd
    dummy change to bump up revision.

    Revision 1.1 1999/12/23 21:58:35 markd
    initial revision



    Note: See the following link for an explanation of possible issues with the use of the $Log: $ tag. http://www.network-theory.co.uk/docs/cvsmanual/Logkeyword.html
    $Locker: $The user who has a lock on this revision (usually nobody) $Locker: markd $
    $Name: $If a sticky tag is in effect, this is the name of that tag. Otherwise blank. $Name: guide_release_1 $
    $RCSfile: $Name of the RCS file in the repository $RCSfile: keyword.html,v $
    $Revision: $Revision number $Revision: 1.3 $
    $Source: $Full path to the RCS ",v" file in the repository $Source: /cvsweb/cvs-guide/keyword.html,v $
    $State: $State of this revision. $State: Exp $
    $CVSHeader: $
    A standard header (similar to $Header: $, but with the CVS root stripped off). It contains the relative pathname of the RCS file to the CVS root, the revision number, the date (UTC), the author, the state, and the locker (if locked). Files will normally never be locked when you use CVS.

    Note: This keyword has only been recently introduced to CVS and may cause problems with existing installations if $CVSHeader: $ is already in the files for a different purpose. This keyword may be excluded using the KeywordExpand=eCVSHeader in the `CVSROOT/config' file. See Configuring Keyword Expansion for more details.

    Bibliography / List of Further Info Links

    Friday, October 1, 2010

    javac -Xlint And Its Many Friends

    -Xlint and its variations - so many to choose from! 1st -Xlint:unchecked

    Or should I just use them all? Pick and choose? Just the one I'm interested in? What to do? What to do?  Like many I came across Xlint(*1) when hitting the following message in one of my Ant builds a while back:

    [javac] Note: Some input files use unchecked or unsafe operations.
    [javac] Note: Recompile with -Xlint:unchecked for details.  

    Huh....I thought to myself....there shouldnt be any errors with my last change. Well looking closer this is just a warning not Ant reporting on a compilation failure.OK. But why does it appear. There doesn't seem to be any location information reporting to me what causes it like a good 'ole stack trace does.  So like countless others I looked up how to use this -Xlint:unchecked thingy and stuck it into my Ant build and re-ran my ant script build.xml......and was promptly swamped by 100's of lines of warning messages (all pretty much saying the same thing) complaining about my absolute poor lack of etiquette in the use (or lack thereof) of generics throughout my (what I thought up until then was) pristine code.  Turns out it wasn't and I was seriously thinking of taking the pesky compile option out since its 'only a warning anyways' and hence thereby effectively getting rid of all that nasty mess and clutter in my build output. 

    Now, okay....I didn't go down that path of just sweeping things back under the rug when they happen to fall out ... and furthermore these days things aren't quite that bad and when I write new code generics are used properly and by default as required throughout the code so this really is more of an issue when converting legacy code or upgrading from Java 1.4 to 5/6+ etc. When I do come across these issues I promptly modify the code to resolve them, thereby not only removing a pesky warning from my pristine build output, clearing up my Netbeans GUI of warnings and .... well .... also as a tiny little almost insignificant side note ..... making the code more robust and providing a higher-level of compile time type safety checking (which is really what generics are all about aren't they!!).

    -Xlint, naked without its ':unchecked' param!

    So now you know all about -Xlint:unchecked for type-checking issues related to generics. It is however possible to simply use just:

    -Xlint

    ....without the :unchecked option. A little naked the poor tool feels now. This effectively says to the compiler use the lint tool (via the -X property) and just call it without any parameters. This has the effect of calling lint and using all of its checks rather than, like in our case above for :unchecked, using just the generic checks/warnings (by passing through the 'unchecked' parameter to the lint tool.

    -Xlint and all of :unchecked's many, many friends!

    So then, what checks are possible? When calling -Xlint what is it that we are actually doing (besides popping up a huuuuuge amount of warnings in most cases).  Well, calling -Xlint is effectively the same as passing in several parameters to the lint tool. What are these parameters....well Ive listed them below as to what it is that you can add to the -Xlint call as arguments to determine what checks the javac compiler should make when compiling the code and what warnings it should then report back on.

    -Xlint:{all,cast,deprecation,divzero,empty,unchecked,fallthrough,path,serial,finally,overrides}


    Thats a lot of options. Here is some info about them from the javac compiler options page:

    -Xlint
    Enable all recommended warnings. In this release, all available warnings are recommended.
    -Xlint:none
    Disable all warnings not mandated by the Java Language Specification.
    -Xlint:-name
    Disable warning name, where name is one of the warning names supported for -Xlint:name, below.
    -Xlint:unchecked
    Give more detail for unchecked conversion warnings that are mandated by the Java Language Specification.
    -Xlint:path
    Warn about nonexistent path (classpath, sourcepath, etc) directories.
    -Xlint:serial
    Warn about missing serialVersionUID definitions on serializable classes.
    -Xlint:finally
    Warn about finally clauses that cannot complete normally.
    -Xlint:fallthrough
    Check switch blocks for fall-through cases and provide a warning message for any that are found. Fall-through cases are cases in a switch block, other than the last case in the block, whose code does not include a break statement, allowing code execution to "fall through" from that case to the next case. For example, the code following the case 1 label in this switch block does not end with a break statement:
    switch (x) {
    case 1:
           System.out.println("1");
           //  No  break;  statement here.
    case 2:
           System.out.println("2");
    }
         
    If the -Xlint:fallthrough flag were used when compiling this code, the compiler would emit a warning about "possible fall-through into case," along with the line number of the case in question.

    -Xlint:{all,cast,deprecation,divzero,empty,unchecked,fallthrough,path,serial,finally,overrides}-cast,-deprecation,-divzero,-empty,-unchecked,-fallthrough,-path,-serial,-finally,-overrides,none}Enable or disable specific warnings


    Links
    http://download.oracle.com/javase/6/docs/technotes/tools/windows/javac.html#nonstandard
    http://mark.koli.ch/2009/04/configuring-ant-to-use-javacs--xlintunchecked-option.html

    *1 - Well not quite....you see thinking back....Ill admit that lint I remember vaguely from my C Programming days back at university (in the dawn of the age in the mists of time back somewhere during the time period range in 1995 - 1999/2000).

    Tuesday, July 13, 2010

    All About The Java Integer Cache


    Java Integer Cache - Introduction

    I recently came across the following System property in Java: java.lang.Integer.IntegerCache.high, and looking into this further brought me to some areas of java I had not yet visited. Having gone in like an intrepid traveller and explored these new, as yet (for me anyway) unknown areas and mapped them for myself I figured the only thing to do know was to share that knowledge with others for future explorers to find their way around.


    So what is this property about?


    Java Integer Cache - Description

    The Java Integer Cache was something that I only discovered recently while at work, even though it has been in the language since Java 1.5. So what is it? Well, as the name suggests its the caching of java integer objects. But, why? Well its required by the JLS (Java Language Specification) for starters which is a pretty compelling reason :-) but its also a performance improvement. The JLS section Im refering to is 5.1.7 Boxing Conversions where in particular it says:


    If the value p being boxed is true, false, a byte, a char in the range \u0000 to \u007f, or an int or short number between -128 and 127, then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.

    So for integers (or also bytes, chars, shorts) in the range of -128 to 127 the spec requires that the Object Wrappers that represent these values (i.e.: Integer, Short, Byte, Char) are cached. Also, interestingly longs are not mentioned in that part of the spec. They are mentioned a little later in a discussion section where it talks about longs but not in section 5.1.7. Despite this, when I looked at the source, the same type of caching code used for int, short, char, byte is also used for longs as well, so they are cached (and rightly so I think) in the same way as the others.


    As I mentioned, this Integer caching was brought in as part of Java 1.5 as a performance improvement. Java 1.5 also introduced Autoboxing of the primitives to their Object Wrapper classes. I think most people who are Java Developers know what Autobxing entails but if you dont then Ill wait here while you have a look at the following link, have a read and then come back...ok...:

    ....good...so your back hey. Alright, well now that you know all about Autoboxing, lets continue on. The cache as a performance improvement is used for all of the autoboxing (well when I say all I mean for any integer primitves, etc., that are within its cache range). Since for using autoboxing requires the use of Object Wrapper classes, even if autoboxing is just an intermediate step...i.e.: take the example of adding and then removing and using an integer in a java.util.List. There is the use of autoboxing when adding the int primitive to the java.util.List, then un-boxing when taking it from the java.util.List back out prior to using it. In this case the client uses only an int primitive from their point of view, but in the background under the covers the VM will use two Integer Wrapper objects. These, like normal objects need to be garbage-collected, take up memory space, etc. Therefor using caching here is definately a performance imrpovement.


    Java Integer Cache - Having a look in the java.lang.Integer java class

    Well, next up lets have a look inside the source code. This is one of the things I love about java and its JDK. The fact that there are no mysterious black box API's is cool. If you want to you can simply, using your favourite IDE and inbuilt short cut, i.e.: <cntrl>+click, jump to the source code and see what it does internally. Note: if it happens to be a native piece of code well thats another matter and you cant simply jump to view the c code...although Id love an IDE plugin for Netebeans that would allow that too. Im sure its achievable....oooh oooh I smell an an open source project brewing. Ha ha ha. Anyways, looking into the source code what do you see? Well in part tht depends is the answer. As I mentioned, this Integer caching was brought in as part of Java 1.5, and the code I show below is the inital code. However since that time it has been upgraded in order to allow the passing of a property that allows you to choose the size of the cache yourself, rather than being limited to the default -128 to 127 from the JDK. So, for interests sake Ill present both versionas, the first being around in Java 1.5 up to when the second version was brought in allowing setting of the casche size in Java 1.6.0_14 (i.e.: the 14th update for Java1.6). Ok, so first version Java1.5.0-->Java1.6.0_13:


    Java 1.5.0_20 - IntegerCache implementation

    private static class IntegerCache {
        private IntegerCache(){}
    
        static final Integer cache[] = new Integer[-(-128) + 127 + 1];
    
        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Integer(i - 128);
        }
    }
    

    Java 1.6.0_14+ - IntegerCache implementation

    The new refactored implementation is below, and some things to note are as follows. For starters the new implementation has some actual comments added in unlike the initial version. Secondly, Ive also added in the static method used to get the system property for setting the cache size static void getAndRemoveCacheProperties(). I figured it would be interesting to show here, plus its used in the IntegerCache as a property so itll be good to see where that property comes from. The only liberty I have taken is to put the IntegerCacahe class first followed byt the other method/property unlike the reverse in the actual code. Thee reasoning being so that its easy to compare the two IntegerCache versions above and below, so keep this in mind:

    private static class IntegerCache {
        static final int high;
        static final Integer cache[];
    
        static {
            final int low = -128;
    
            // high value may be configured by property
            int h = 127;
            if (integerCacheHighPropValue != null) {
                //Use Long.decode here to avoid invoking methods that require Integer's autoboxing cache to be initialized
                int i = Long.decode(integerCacheHighPropValue).intValue();
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - -low);
            }
            high = h;
    
            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }
        private IntegerCache() {}
    }
    
    /**
     * Cache to support the object identity semantics of autoboxing for values between -128 and 127 (inclusive) as required by JLS. 
     * The cache is initialized on first usage. During VM initialization the getAndRemoveCacheProperties method may be used to get and remove any 
     * system properites that configure cache size. At this time, size of cache may be controlled by the vm option -XX:AutoBoxCacheMax=<size>.
     */
    // value of java.lang.Integer.IntegerCache.high property (obtained during VM init)
    private static String integerCacheHighPropValue;
    
    static void getAndRemoveCacheProperties() {
        if (!sun.misc.VM.isBooted()) {
            Properties props = System.getProperties();
            integerCacheHighPropValue = (String)props.remove("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null)
                System.setProperties(props);  // remove from system props
        }
    }
     
    

    Java 1.5.0_20 - Java 1.6.0_14+ - IntegerCache implementation comparisons/diffs.

    Ok, so lets look at the diffs here. For starters lets look at the IntegerCache class itself. In both cases its a private static. Furthermore the general layout is similar. An Integer[] array for holding the cached values of the Integer objects. However the introduction of the property for setting the cache size now changes teh way this cache array is defined. Lets take a look at the two definitions, Java1.5 first followed by the refactored version:

    static final Integer cache[] = new Integer[-(-128) + 127 + 1]; static final Integer cache[];

    So as you can see, the Java1.5 initial version was simpler and it defined the array size in the definition of the array because it knew the size striaght up. The new version doesnt know the size until it checks the appropriate system property so it cant define the array size until later. Its also interesting that the array size in th first version is defined as: -(-128) + 127 + 1, rather than 256. I can see the reason I suppose as by define it this way it makes it clearer why this size was chosen with the references to the cache range in the definition (i.e.:-128 to 127) and it only adds 3 extra operations so performance loss is minimal (especially since the operations are just additions and in all likelihood they are optimised away by the compiler into a single value anyway.

    Ok so what else?. Well the Java1.5 version fills the cache like so:

        for(int i = 0; i < cache.length; i++)
            cache[i] = new Integer(i - 128);
    

    A simple for loop over the value which is the cache.length ranging from the negative to postive range by the use of the: (i - 128) which uses the cache size and subtracts 128 from each value to create the ppropriate range. The new version first decodes the sytem property. It gets the property using static void getAndRemoveCacheProperties()with the property name being: java.lang.Integer.IntegerCache.high. Then prior to setting up the cache it determines teh high and low values for the range from this property. The next few lines do the following:

    1. int i = Long.decode(integerCacheHighPropValue).intValue(); - Decode the property String into an integer primitive and assign to a temp variable 'i'. Furthermore as the comment above the line specifies we use the Long classes decode method and then convert to an int primitive rather than using Integer to do so which would be quicker/simpler, but since we are initialising the cache for Integer we have to stay away from the class and its methods and hecne the use of the Long.decode() and Long.intValue() method uses.
    2. i = Math.max(i, 127); - Determine the maximum from the property and 127. The purpose of this being to make sure that the value that you pass in is AT LEAST the size of the default cache size as required by the JLS Spec. If you enter a smaller value then 127 this line hence ensures that 127 is used as the cache size/range.
    3. h = Math.min(i, Integer.MAX_VALUE - -low); - This sets up the maximum size of the array. Seems counter intuative to do this since we already did the Math.max() call above, but this call is to be safe and make sure that we dont have a array overload exception. If the value passed in through the property is large enough without this line it could cause the array to overflow. Hence the min() in conjunction with Integer.MAX_VALUE - -low, call here to makesure we dont overflow.
    4. Finally, the Integer[] cache is setup in much the same way as in the first version now that we know the low and high values with a loop creating new Integer() instances over the low to high range.

    Now, one very interesting thing that I found out while examining this code was unexpected. Given the following example where I pass in the property -XX:AutoBoxCacheMax=<size> using size=1000, I would've thought, prior to this that the cache would've been from -1000 to 999 or perhaps -1001 to 1000. In actual fact the range of the cache is from -128 to 1000 in this case. Its an interesting side affect of this code that it is not possible to add more negative values to the cache besides the default 0 to -128 even though it is possible to add higher positive values. I think that in the future a java.lang.Integer.IntegerCache.low property should be added with the vm option -XX:AutoBoxCacheLow=<size>. In fact I intend to suggest this to the JDK7 project as a minor API/VM change (along with a patch for the code) as I can see no reason why adding a similar property for a max low in the cache wouldnt be acceptable given the max high is already in. Watch this space for further info on how I go :-) .

    Integer.valueOf(int i)

    public static final Integer valueOf(int i) Description and Purpose

    The provision of the IntegerCache has lead to new rule/pattern for the creation of Integer instances. The public static Integer valueOf(int i) method has been provided in the Integer class API as of Java1.5 and it returns an Integer instance representing the specified int value. If a new Integer instance is not specifically required, which in most cases there should be no reason for requiring an Integer for the same primitive int but with a different hashcode, this method should generally be used in preference to the constructor version (new Integer(int)), as this method is likely to yield significantly better space and time performance by caching frequently requested values.

    Java 1.5.0_20 - Java 1.6.0_14+ - Integer.valueOf() implementation comparisons/diffs.

    As a final side note for this blog entry I just want to take a quick look at the comparison of the valueOf() method and its implementation and specifically the differences between the two versions. They are shown below:

    This is Java1.5 Integer.valueOf(int i):

        public static Integer valueOf(int i) {
            final int offset = 128;
            if (i >= -128 && i <= 127) { // must cache 
                return IntegerCache.cache[i + offset];
            }
            return new Integer(i);
        }
    
    This is Java1.6 Integer.valueOf(int i):
        public static Integer valueOf(int i) {
            if(i >= -128 && i <= IntegerCache.high)
                return IntegerCache.cache[i + 128];
            else
                return new Integer(i);
        }
    

    While the two implementations are almost identical, its intersting to see the minor differences in their implemnetation. Given that the actual implementation is the same in intent its intersting to see that the developer decide to make these minor changes if they have no functionality difference. In particular, the older version defines a final int offset = 128 whereas the newer version removes this initialisation and just uses the number (magic number) in the code. Why would they do this ? Its better coding practice to not use magic numbers. The newer version also uses a 'else' clause for returning the default new Integer(i) value if not returning from the cache. In the older verison there was no else. Like I said, in terms of intent ther is no difference but why these two changes. Also, one change which does have a purpose is the use of IntegerCache.high rather than 127 for the if statement comparison. This is required since by defining the cache high watermark we can no longer use the magic number 127.

    Sources / Bibliography

    The following links where either a direct help/reference in writing up this article or are simply good for elaborating on various concepts described above (especially for concepts around the edges and not directly part of the Java Integer Cache concept Im describing, such as autoboxing, generics, the new features introduced in Java 5 etc.