Warning Hunt: OpenJDK, NetBeans, Warnings, and FindBugs
2009-06-15 17:21:55


Did you see Bill's FindBugs slides from JavaONE 2009? You should create some step by step directions on getting started with NetBeans, FindBugs and the OpenJDK. We need to get developers working on this.
Humm, Ok, I'll look into that.
Don't just "look into it", do it!
Ok ok already, I'll "do it".
And try and talk about how to fix warnings, and especially the FindBugs errors, maybe talk about some kind of best practices.
Yeah yeah, and I'll take care of the world peace problem too.
Smart ass, how did you ever get this job in the first place.
Everything else I wanted to do was illegal, creating software seemed like the most criminal thing I could do that wouldn't put be in jail.
Oh geez, why does this seem like a Dilbert comic? Get to work!
Aye aye Captain! Batton down the hatches, full speed ahead, we be looking for the White Whale...
"Drink, ye harpooners! drink and swear, ye men that man the deathful whaleboat's bow -- Death to Moby Dick!"
Oh for heavens sake, maybe you should look into a mental institution.

Ok folks here we go...

My sincere apologies to the Whales and Whale lovers out there, just remember Moby Dick is just a fictional story and I am in no way condoning the slaughter of those innocent and fantastic animals.

NetBeans, FindBugs, and Hunting Moby Dick

For a developer that wants to actually change the source code, the very best way to work with a tool like FindBugs is through an IDE.

  1. Get .

    Download and install NetBeans 6.5.1, I used the smallest "Java SE" version but any one of the "Java" versions will do. It installs quickly and easily. I would normally recommend the newer NetBeans 6.7, and I am trying 6.7 myself right now, but so far I have been unable to get the other steps below to work with 6.7, so I'd stick with 6.5.1 for now.

  2. Turbo charge it .

    Configure the NetBeans memory settings for the best performance, this is optional. See my NetBeans performance blog. Effectively we want to boost the memory sizes to improve the interactive experience. Of course, if you have less than 1Gb RAM, you may want to avoid this:

    
    Mac<1> mkdir -p ${HOME}/.netbeans/6.5.1/etc
    Mac<2> cat >> ${HOME}/.netbeans/6.5.1/etc/netbeans.conf
    netbeans_default_options="-J-Xms256m -J-Xmx512m -J-XX:PermSize=32m -J-XX:MaxPermSize=160m
    -J-Xverify:none -J-Dapple.laf.useScreenMenuBar=true -J-XX:+UseConcMarkSweepGC
    -J-XX:+CMSClassUnloadingEnabled -J-XX:+CMSPermGenSweepingEnabled"
    
  3. Get FindBugs .

    The NetBeans FindBugs plugin is a bit hard to find. You need to tell NetBeans where the UpdateCenter center is that has this plugin. The NetBeans plugin is not maintained by the FindBugs developers. To do this you need to start up NetBeans 6.5.1 and do the following:

    1. Select "Tools->Plugins".
    2. Select "Settings".
    3. Select "Add"
    4. Enter any name you want in the "Name:" field, and for the "URL:" field use:
      https://sqe.dev.java.net/updatecenters/sqe/updates.xml
      then select "OK".
    5. Select "Available Plugins", select the "SQE Java" plugin, select "Install", and go through the plugin install process.
    You should now see several new icons in NetBeans, specifically the icons for the SQE site , the FindBugs tool , and the PMD tool . My experience with FindBugs has been very positive and I trust this tool completely, rarely has it been wrong or given bad advice. On PMD, you will note that the PMD tool has the image of a gun in it's icon, for a good reason, be very careful with PMD, shooting yourself in the foot is pretty easy to do.
  4. Find a NetBeans project to play with. My first example is jmake, a small Java project available from kenai.com. Get yourself a clone with:
    hg clone https://kenai.com/hg/jmake~mercurial ${HOME}/jmake
    Then use the NetBeans "Open Project..." to open up this directory ${HOME}/jmake as a NetBeans project. It should load up fine, build cleanly, and you can try using FindBugs to look at and even fix some of the bugs.
    Note: You need to be a developer member of the jmake project to push changes back.

    Or you can get sources, and either find a NetBeans project or create one. I chose to create one and picked the jdwpgen tool in the jdk/make/tools/ directory. So I did this:

    1. Cloned the OpenJDK sources (just a partial forest):
      hg clone http://hg.openjdk.java.net/jdk7/jdk7 ${HOME}/myjdk7
      cd ${HOME}/myjdk7
      hg clone http://hg.openjdk.java.net/jdk7/jdk7/jdk
    2. Tell NetBeans to create a "New Project", pick "Java Project with Existing Sources", naming the project "jdwpgen", and I'll locate this throw away project at ${HOME}/jdwpgen, then select "Next".
    3. Then I tell it to use the source directory ${HOME}/myjdk7/jdk/make/tools/src/, and select "Next".
    4. Then I specify build/tools/jdwpgen/** in the "Includes", and select "Finish" to complete the project definition. This process should work for any clean subset of Java sources in the OpenJDK, but I can't attest to that fact, yet.
    5. Try a build (should compile 50 files or so), run FindBugs, try and fix something.
      Note: You will need to be a member of the OpenJDK project and be able to create correct changesets to push changes back, this normally requires a BugID, and will require that certain changeset comment and whitespace rules are followed. (Yeah yeah, I know we are working on this, someday I'll be able to describe this better and it will all be open and completely logical ;^). Anyone outside of Sun that has tried to push changes into OpenJDK will confirm how difficult this currently is, but we are working on it.

That's it, play with it, try fixing FindBugs errors or compiler warning errors. Aye, we didn't manage to kill Moby Dick, but we sure sunk in a few good harpoons.

Command Line Usage

The FindBugs and PMD tools can be run from the command line to create all kinds of reports. You will need to download and install FindBugs and/or PMD of course.

Some sample FindBugs command lines:

findbugs -maxHeap 512 -textui -effort:default -low -exitcode ${HOME}/jdwpgen/dist/jdwpgen.jar
findbugs -maxHeap 512 -textui -effort:default -low -exitcode -xml:withMessages -output ${HOME}/jdwpgen/build/findbugs.xml ${HOME}/jdwpgen/dist/jdwpgen.jar

Some sample PMD command lines:

pmd.sh ${HOME}/myjdk7/jdk/make/tools/src text basic,imports,unusedcode
pmd.sh ${HOME}/myjdk7/jdk/make/tools/src xml basic,imports,unusedcode > ${HOME}/jdwpgen/build/pmd_out.xml

Of course the catch is, I'll be fixing jdwpgen, so don't even think about pushing changes in before me.

Mac, NetBeans/Ant, and PATHs

FYI... anyone that works with Ant scripts (all NetBeans users) has found out that the best way to get the Ant <exec> to work well is to set PATH properly, but controlling PATH from a GUI launch is tricky. For the Mac see my previous post on NetBeans, Mac and PATHs, which explains the Mac tricks needed to set the PATH for NetBeans.

For Developers, Hudson IS The Answer...

Have you used Hudson? If you haven't, you should, I'll blog about it more very soon, but to get yourself started, do this:

  1. Download Hudson (hudson.war)
  2. In a separate shell window, run:
    java -jar hudson.war
  3. Go to http://localhost:8080/ and play with your very own Hudson, create a new job, browse the many plugins available,...

I'll talk about Hudson and how to connect it up to FindBugs, PMD, Warning Messages, etc. in a future blog...

-kto

Ant and Importing
2009-06-15 11:21:37

Just how many copies of junit.jar have been added to source repositories on the planet? Quite a few I imagine, seems like a waste of repository data space and well, just wrong. Not junit, which is a fantastic product, just the fact that we have so many copies. Granted you have gained a pretty stable tool by freezing the version you have, and you have guaranteed having a copy at all times, but is it a good idea to add all these binary fines to your repository data? As the list of tools like this grows and grows, does the "just add it to the repository" solution continue to scale? And each time you need a new version, you end up adding even more binary data to your repository.

Some projects have taken to doing a kind of "tools bootstrap" by downloading all the open source tools the first time you setup a repository, making the files immune from normal 'ant clean' actions. Ant has a a task called <get> which can allow you to download tool bundles and it works quite well, but there are some catches to doing it this way. Expecting all the download sites to be up and available 24/7 is not realistic. And predictability is really important so you want to make sure you always download the same version of the tools, keeping a record of what versions of the tools you use.

So what we did in the openjfx-compiler setup repository, was to create an import/ directory to hold the downloaded tools, automate the population of that area with the <get> task, and also allowed for quick population of import/ with a large import zip bundle. The initial version of the repository had a very similar mechanism, so this idea should be credited to the original authors on the OpenJFX Compiler Project.

This logic is contained in the file build-importer.xml of the setup repository and for each tool NAME downloaded, a set of properties is defined (import.NAME.*), and 2 ant tasks import-get-NAME and import-NAME. Probably best to look at the bottom of this file first. As before quite a few macrodefs were used to make this all work.

Your browser does not support iframes.

The ant build script then just uses ${import.junit.jar} to get a junit.jar file.

You can actually try this out yourself pretty easily if you have Mercurial (hg) and ant by doing this:

hg clone https://kenai.com/hg/openjfx-compiler~marina-setup setup
cd setup
ant import

Of course I'll predict that it fails the first time for 50% or more people, this kind of downloading is just not that reliable when depending on all these sites. So you may have to run ant import a few times.

-kto

Ant and Platform Specific macrodefs
2009-05-26 13:22:20

Ant works great for any pure Java project, very simple to deal with, might get a little tricky when dealing with jar manifests, but not bad, and very efficient in terms of limiting the Java VM startup overhead. But what about platform specific tasks? I myself find the "<exec>" ant task so painful to use that I avoid it at all costs, or at least isolate each use to a "<macrodef>". And this macrodef isolation actually works pretty well when you are dealing with many different platforms that you need to build on.

There are many solutions to the issue of platform specific builds, including the ant cpptasks and I am sure many more. So what I am saying here is not new and not the end all to this issue. Just some ideas for people to consider when up against this problem. Please, add your comments if you have some good references and ideas. It's very obvious to me that I am no where near an ant expert, so take all this with a grain of salt. I also want to give credit to the many JavaFX teams and individuals you wrote the various ant scripts in all the repositories, most of this is a consolidation of other peoples ideas and techniques.

So how did the JavaFX SDK deal with multiple platform issues in ant? This project was composed of many sub repositories, each with different system needs and often using slightly different techniques for building. The top repository (or setup repository or root repository) we have allows for this independence as much as possible, but at the same time trys to create some kind of structure to the build process. From the Mercurial file view of the openjfx-compiler setup repository, I will try and explain what is happening.

The JavaFX SDK project is a bit unique, and the techniques used in it's build process may not suit many projects, but I thought some of this might be of interest to anyone considering putting their hand into any large ant nest someday. :^)

Hope someone has found this helpful, as always, comments on better ideas is always welcome.

-kto

Painful Ant Bite: A generous CLASSPATH and ant.bat out of hell
2009-05-06 21:22:19

-kto

Fedora 9 and Mac VMware Fusion 2.0.4
2009-05-03 22:51:14

Thought I would provide some notes on setting up a Fedora 9 VMware image on my Mac laptop using VMWare Fusion 2.0.4. I used the same steps for both Fedora 9 32bit (i386) and 64bit (x86_64), however I had some trouble with installing x86_64, even seemed to trigger a MacOS panic at one point after doing the yum update, not sure what that was all about, only happened once. This was strictly a local Fedora install, so I didn't need to deal with any of the networking issues of setting up a real physical machine.

I'll try and re-create the order of things as best I can:

  1. Create VMware Virtual Machine from Fedora 9 install iso image. I set it up to have a 20GB disk (You cannot change this disk size afterwards!). I'm using 768Mb RAM (512Mb caused slow builds) and during the install I asked for the "Software Development" packages.

  2. Update your system and make sure you have all you need. Logged in as root:

    yum install kernel kernel-headers kernel-devel
    yum install hg ksh tcsh csh cups cups-devel freetype freetype-devel lesstif-devel
    yum groupinstall "X Software Development" "Development Tools" "Java Development"
    yum update
    
    This will take a while. A reboot after you are all done would be a good idea.
  3. Install VMware tools. Once you extract out the VMware tools folder vmware-tools-distrib, once again logged in as root do the following:

    cd vmware-tools-distro
    ./vmware-install.pl
    
    The list of questions to answer is long and convoluted, mostly the default answer works fine, but in some cases it seems to think you are using a remote login and you have to say "yes" to continue the installation.
  4. Mouse problems: For some reason all my single clicks were being treated as double clicks, which drove me nuts. I found this posting which solved the problem, I use option 2 and edited the file /etc/X11/xorg.conf and added the following lines, logged in as root:

    Section "ServerFlags"
            Option      "AutoAddDevices" "false"
    EndSection
    
    A reboot of your virtual machine is necessary to fix this.
  5. The default limit on file descriptors is very low, to allow for a larger limit the following addition to the file /etc/security/limits.conf will increase that limit, again logged in as root:

    ################################################
    * soft nofile 64000
    * hard nofile 64000
    ################################################
    
    You need to logout and back in for these new limits to be available.
  6. Recently it was discovered that the upgraded kernel-headers package has trimmed down the files it delivers to /usr/include/linux/ (i.e. dirent.h) and although this doesn't impact OpenJDK building, it could impact builds of parts of the Sun JDK (plugin). So to avoid this missing include file problem, you have to do this last step because the above steps need the latest and matching kernel-headers files. To get the older kernel-headers package run:

    yum remove kernel-headers glibc-headers
    yum install kernel-headers-2.6.25 glibc-headers
    
    Bugs have been filed on the Sun JDK to see if we can break this dependency on the /usr/include/linux/ files.

That's the basic system setup. In addition I also setup my own home directory with the following so I can build the OpenJDK:

  1. Get webrev tool:

    mkdir -p ${HOME}/bin
    cd ${HOME}/bin
    wget http://blogs.sun.com/jcc/resource/webrev
    chmod a+x webrev
    
  2. Get latest ant:

    mkdir -p ${HOME}/import/ant_home
    cd ${HOME}/import/ant_home
    wget http://www.apache.org/dist/ant/binaries/apache-ant-1.7.1-bin.tar.gz
    tar -xzf apache*.tar.gz
    mv apache-ant-1.7.1/* .
    
  3. Get forest extension:

    mkdir -p ${HOME}/hgrepos
    cd ${HOME}/hgrepos
    hg clone http://bitbucket.org/pmezard/hgforest-crew hgforest
    
  4. Setup your ${HOME}/.hgrc file:

    cat > ${HOME}/.hgrc <<EOF
    [ui]
    username = ${USER}
    ssh = ssh -C
    [trusted]
    groups = wheel
    [extensions]
    fetch=
    purge=
    mq=
    forest=${HOME}/hgrepos/hgforest/forest.py
    [defaults]
    clone = --pull
    fclone = --pull
    fetch = -m Merge
    ffetch = -m Merge
    EOF
    
  5. Get OpenJDK7 sources (jdk7 build source forest):

    mkdir -p ${HOME}/hgrepos/jdk7
    cd ${HOME}/hgrepos/jdk7
    hg fclone http://hg.openjdk.java.net/jdk7/build jdk7-build
    
  6. Get OpenJDK6 sources (jdk6 master source forest):

    mkdir -p ${HOME}/hgrepos/jdk6
    cd ${HOME}/hgrepos/jdk6
    hg fclone http://hg.openjdk.java.net/jdk6/jdk6 jdk6-master
    

You need some patches to OpenJDK6 to build on Fedora 9. Primarily to hotspot (until it gets updated with a newer version), more minor ones to corba and jdk to get rid of the findbugs dependence logic which isn't critical for building. These patches are hopefully a temporary situation.

jdk6/hotspot

Your browser does not support iframes.

jdk6/jdk

Your browser does not support iframes.

jdk6/corba

Your browser does not support iframes.

Now to see if I can build both OpenJDK7 and OpenJDK6:


# To get rid of a few sanity errors
unset JAVA_HOME
LANG=C
export LANG

# My own private copy of ant
ANT_HOME=${HOME}/import/ant_home
export ANT_HOME

# Use the JDK that is part of Fedora 9
ALT_BOOTDIR=/etc/alternatives/java_sdk_1.6.0
export ALT_BOOTDIR

# Add java and ant to the PATH
PATH="${ALT_BOOTDIR}/bin:${ANT_HOME}/bin:/usr/local/bin:/usr/ccs/bin:/usr/ccs/lib:/usr/bin:/bin:/usr/bin/X11:/usr/sbin:/sbin"
export PATH

# Go to the root of the jdk7 source forest
cd ${HOME}/hgrepos/jdk7/jdk7-build

# Build jdk7
#  Don't run javadoc, too slow, needs 1024Mb RAM minimum
make NO_DOCS=true

# Go to the root of the jdk6 source forest
cd ${HOME}/hgrepos/jdk6/jdk6-master

# Build jdk6
#  Empty WARNINGS_ARE_ERRORS gets rid of -Werror option, too many warnings
#  Don't run javadoc, too slow, needs 1024Mb RAM minimum
make WARNINGS_ARE_ERRORS=  NO_DOCS=true

SUCCESS! They both build.

-kto

Windows Visual Studio Stupid Pet Trick of the Day
2009-04-14 15:52:09

I've blogged about vcvars32.bat and ant before, but I decided to take it a step further.

I'm constantly having to deal with different versions of Visual Studio and am always in need of having to run those silly vcvars32.bat files so the appropriate environment variables get set, but to run them you need to be in a Windows command shell, which I never use. So this is my Windows Visual Studio Stupid Pet Trick of the Day, for you CYGWIN Visual Studio Users, the vsvars.sh script.

The vsvars.sh script will exec a Windows command shell, have it spit out the environment variables it sets, and then it echos out shell environment variable setting commands. And here it is:

Your browser does not support iframes.

Running "vsvars -s" will get you something like:

Your browser does not support iframes.

Nasty looking stuff, but guaranteed to be what the official Visual Studio vcvars32.bat (or vsvars32.bat) files do to the Windows command shell environment.

The nice thing is that if you use it like so:

It works pretty slick... although I can't possibly test it in all situations.

This will probably be hooked into the JDK builds at some point, or provided with those sources.

-kto

JavaOne 2009 is coming soon...
2009-04-13 18:22:19

Where will YOU be June 2?

Don't forget to sign up for JavaOne 2009! You can browse the Online Catalog and see the huge list of talks and sessions this year.

Just a few technical sessions on my list:

-kto

Source Repository Rules
2009-04-13 10:24:03

A few commandments for dealing with Software repositories (source bases) and the build results of those repositories.

OL.withroman { list-style-type: upper-roman }
  1. There shalt not be binary files in the repository.
    Binary files (executables, native libraries, zip files, jar files, etc.) are NOT source and should not be managed in a source repository.
  2. Keep thy path names simple.
    Directory names and filenames in the repositories should never contain blanks or non-printing characters. Certain characters such as '$' should also be avoided.
  3. There shall be one newline convention.
    The contents of all source files should follow the standard unix conventions on newlines (no ^M's).
  4. Generated source files shall not be added as managed files.
    Source files generated during the build process should not be managed files in a repository.
  5. All output from the build shall be kept separated from the source.
    All files generated during the build should land in a well defined output only directory such as build/ or dist/. The src/ directory should never get written to during the build process.

Of course the commandments will change from time to time. Reminds me of this scene in Mel Brooks "History of the World Part II" movie, loved the ending "These 15 Commandments... oops... 10 Commandments!". ;^)

-kto

Where has JVMPI gone?
2009-04-13 10:24:03

Have you seen this error before?


FATAL ERROR: JVMPI, an experimental interface, is no longer supported.
Please use the supported interface: the JVM Tool Interface (JVM TI).
For information on temporary workarounds contact: jvmpi_eol@sun.com

For a long time now, since we released JDK 1.5, we have been warning people that the VM profiling interface JVMPI is going away. Starting with the JDK 6 update 3 release (JDK6u3), it is gone for good.

If you really need JVMPI, your best bet is to use a JDK 1.5 or older release, and also find out about transitioning to JVM TI. More often than not, you have become dependent on a tool that uses JVMPI, in which case you should try and upgrade that tool to a version that uses JVM TI instead. But if you have written your own JVMPI code, see the JVMPI transition article at http://java.sun.com/developer/technicalArticles/Programming/jvmpitransition/ for help in transitioning to JVM TI.

NOTE: Getting this message indicates that JVMPI has been requested of the JVM. A request for JVMPI must be made prior to JVM initialization and regardless of whether JVMPI is eventually used at runtime, just the request for it will have a negative performance impact on your Java application. In most situations, JVMPI should never be requested unless some kind of performance work is being done and slower performance is considered acceptable. JVM TI does not have many of the JVMPI limitations.

A few references of interest:

-kto