Monday, January 30, 2012

Null Analysis for Fields with Eclipse JDT

It is common knowledge that Eclipse has an intra-procedural null analysis capability, augmented recently with null annotations for inter-procedural analysis in Juno M4. However, a big flaw and pain point till now was that the anlsysis would only work for local variables/parameters, and NOT for fields! Strange, innit? Well, a bunch of problems with handling fields prevented the initial null analysis implementation to be generic enough to handle fields as well. Access from different threads, through different objects, initialization of even final fields in different constructors were some of the roadblocks because of which this work was put on the backburner. However, even though we haven't found a holy grail to tackle these problems, we've come out with atleast a basic implementation of null analysis for fields! Rejoice!

A. The Problem
Prior to Juno M5, the following code snippet would raise null warnings only on the local variable, but not on the field.


B. The Solution
See the Juno M5 new and noteworthy page for the new null analysis for fields.
Note that for non-constant fields, we only raise "potential NPE" warnings even if the field has been assigned null or compared against null because we assume that there's always a chance of another thread modifying it between the assignment/comaparison and the actual reference. So consider the following snippet


C. Not quite there yet?
There are a few limitations with the current null analysis for fields:
  • Yet to be done for final fields that are initialized at the time of declaration. This will be done with the fix for bug 237236 soon.
  • The analysis only works for non-static fields of the current object or static fields of the current type ONLY. That means, in the following code snippet. you get null warnings on direct access of field1 or access via "this", but not if field1 is accessed via another object 'test'.
class Test{
   public Object field1;

   void foo(Test test) {
      if (field1 == null) { 
         System.out.println( field1 .toString());  // "potential" NPE warning
     } else {
        // do something
     }
     System.out.println(field1.toString());  // Potential NPE warning here

     if (this.field1 == null) { 
         System.out.println( this.field1 .toString());  // "potential" NPE warning
     } else {
        // do something
     }
     System.out.println(this.field1.toString());  // Potential NPE warning here
    // access through object 'test' will raise no warnings. See below

     if (test.field1 == null) { 
         System.out.println( test.field1 .toString());  // no warning
     } else {
        // do something
     }
     System.out.println(test.field1.toString());  // no warning


  }
}

This is a limitation of the current code analysis infrastructure and we hope to address this sometime soon. The soon to be released null annotations support for fields will greatly assuage this problem in the short term.

Please do start using this new feature. Even with its limitations, its quite useful and we've found a long list of unsafe code patterns in the Eclipse SDK itself. Deepak's post here presents one such example


Apart from this, Juno M5 has more interesting items. See my previous post on pre-built indexes, Stephan's post on Resource leak warnings and the Juno M5 new and noteworthy page for more.

Stay tuned!



Thursday, January 26, 2012

Faster Java search using pre-built indexes with Eclipse JDT

JDT indexes referenced libraries (or JARs) in your projects for use in the Java search. However, in most cases these libraries seldom change, and the indexing may be costly and take time when you invoke search for the first time after adding the JAR on the buildpath.

From 3.8M5 onwards, you can avoid this redundant indexing by providing a pre-built index for each classpath entry in the classpath container. This feature was recently implemented in bug 356620.

So how do you generate the indexes in the first place?
1. Create the JAR
2. Go to Run Configurations>Eclipse Application. Give a name to the configuration, viz. indexer, and in 'Main' tab choose Run an application, and use the list to select org.eclipse.jdt.core.JavaIndexer

3. Go to the 'Arguments' tab and use the arguments -option <indexFileLocation> <jarFileLocation> in addition to the existing ones.

4. The index file will be generated at the specified location.

Now when the JAR in question is being added to the build path of a project, the classpath containers can add the index location to classpath, which will look as follows:

<classpathentry kind="lib" path="C:/Users/IBM_ADMIN/Desktop/TestIndex.jar">
<attributes>
<attribute name="javadoc_location" value="file://C://abc"/>
</attributes>
</classpathentry>

Voila! JDT will no longer index the JAR and even the first search will be lightning fast!

Note: This feature is mainly intended for plug-ins that implement their own classpath container, not for the end user.