Archive

Archive for January, 2009

Building the OpenJDK on Ubuntu 8.10

January 3rd, 2009

When I asked a colleague at work what I should do during my vacation, he said build the OpenJDK… so I did!

In hindsight, it would have been easier to have built IcedTea (RedHat’s OpenJDK hybrid) rather than Sun’s raw OpenJDK. However since I spent quite a bit of time setting up the environment I was determined to get it to build.

At a high level I did the following:

  • Downloaded the source (~ 85Mb): http://download.java.net/openjdk/jdk7/.
  • Downloaded the binary plugins (the bits of the OpenJDK that are yet to be open sourced).
  • Downloaded the dependencies.
  • Modified some environment variables.
  • Checked the environment is ok via the sanity script.
  • Made 1 change to the source code.
  • Made 1 change to the make compiler flags.
  • Ran the build.

The README file did not cover all of the dependencies needed to build the OpenJDK on Ubuntu, here is what worked for me:

  • sudo apt-get install build-essential
  • sudo apt-get install gawk
  • sudo apt-get install m4
  • sudo apt-get install libasound2-dev
  • sudo apt-get install libcupsys2-dev
  • sudo apt-get install sun-java6-jdk
  • sudo apt-get install x11proto-print-dev
  • sudo apt-get install libxp-dev
  • sudo apt-get install libfreetype6-dev
  • sudo apt-get install libxt-dev
  • sudo apt-get install libxtst-dev

The OpenJDK comes with a script (jdk/make/jdk_generic_profile.sh) to help set up your environment. The main updates I needed to make were:

  • The bootjdk variable which holds the folder name of your Java 6 install.
  • The jdk_instances variable which holds the parent directory of your bootjdk.
  • The binplugs variable which holds the location of the non open source bits of the OpenJDK.
  • Ensure ANT_HOME was exported.
  • Ensusre ANT_HOME/bin was on the PATH.

You can see my full environment here: jdk_generic_profile.

The environment was then verified using the sanity make target:

 
$ . jdk/make/jdk_generic_profile.sh
$ make sanity

Once this passed I tried building but got a couple of errors.

The first error was:

 
/openjdk/hotspot/src/share/vm/libadt/port.hpp:
In function 'void bcopy(const void*, void*, size_t)':
/openjdk/hotspot/src/share/vm/libadt/port.hpp:40:
error: 'void bcopy(const void*, void*, size_t)' redeclared inline
without 'gnu_inline' attribute
/usr/include/bits/string3.h:90:
error: 'void bcopy(const void*, void*, size_t)' previously defined here
make[6]: *** [incls/_precompiled.incl.gch] Error 1

I understand what the error means but I could not work out why the error occurs because after looking through /usr/include/string.h, the include of /usr/include/bits/string3.h is only done if the user specifies _FORTIFY_SOURCE which as far as I can tell is not done in the OpenJDK. My workaround is quite simple, I commented out the redeclaration of inline void bcopy(const void*, void*, size_t) since it appears to already be inlined somehow.

The second error was:

 
/openjdk/hotspot/src/share/vm/runtime/arguments.cpp:
In static member function 'static void Arguments::set_aggressive_opts_flags()':
/openjdk/hotspot/src/share/vm/runtime/arguments.cpp:1359:
error: format '%d' expects type 'int', but argument 3 has type 'intx'

This occurs because of a flag that treats WARNINGS as ERRORS. The correct approach would have been to go and fix the warnings, instead I disabled the flag WARNINGS_ARE_ERRORS = -Werror which can be found in hotspot/make/linux/makefiles/gcc.make.

After making these changes I was able to run the build (just typed make) and saw the following output in the end:

 
Control linux amd64 1.7.0-internal build_product_image build finished:
Control linux amd64 1.7.0-internal all_product_build build finished:
Control linux amd64 1.7.0-internal all build finished:

I had a working JDK which could be found in build/linux-amd64/j2sdk-image/bin.

 
$ ./java -version
openjdk version "1.7.0-internal"
OpenJDK Runtime Environment (build 1.7.0-internal-jeffsinc_2009_01_03_10_52-b00)
OpenJDK 64-Bit Server VM (build 14.0-b09, mixed mode)

java ,

APT v AspectJ

January 2nd, 2009

APT has interested me for quite some time because after reading various blog entries and articles, it was unclear to me where APT fits in relation to other tools that provide functionality triggered by annotations. Specifically I’ve been interested in any overlap between APT and AspectJ.

Both AspectJ and APT provide the following common functionality:

  • Ability to intercept annotations.
  • Ability to declare custom compiler errors and warnings based off annotation matching.

I attempted to implement an architecture enforcement requirement using both tools. The requirement was simple: a compile error should occur when an attempt is made to access a class annotated with @RestrictedResource unless the caller is annotated with @SuppressRestrictions.

This was relatively simple with AspectJ, the following Aspect provides the enforcement:

 
public aspect RestrictedResourceEnforcer {
    private pointcut accessToRestrictedResource() :
        call(* (@RestrictedResource *).*(..))
                || call((@RestrictedResource *).new(..));
    private pointcut withinUnrestrictedCode() :
        @withincode(SuppressRestrictions) || @within(SuppressRestrictions);
    declare error : accessToRestrictedResource() && !withinUnrestrictedCode():
        "Attempt to access a restricted resource.";
}

The following test demonstrated the compiler error as well as the lack of compiler error should @SuppressRestrictions be used:

 
public class RestrictedResourceEnforcerTest {
    public void testAccessToRestrictedResource() {
        // Compile error: attempt to access restricted resource.
        RestrictedClass restrictedClass = new RestrictedClass();
        // Compile error: attempt to access restricted resource.
        restrictedClass.method1();
    }
    @SuppressRestrictions
    public void testAccessToSuppressedRestrictionResource() {
        RestrictedClass restrictedClass = new RestrictedClass();
        restrictedClass.method1();
    }
    @RestrictedResource
    private static class RestrictedClass {
        public void method1() {
        }
    }
}

Immediately I realised that it is not possible to implement this kind of architecture enforcement using APT without annotating the calling class (i.e RestrictedResourceEnforcerTest). Without marking the calling class, I’m not going to get a process() callback from APT.

This attempt has shown me that APT is only of real use for processing that is completely contained within the annotated class.

I still wanted try APT in direct comparison with AspectJ so I tried enforcing immutability on any class with an @Immutable annotation. I gave up pretty quickly using APT for this because although it is technically possible, it requires a lot of work with ASM to generate the correct source to enforce immutability (i.e. return unmodifiable collections on getters, throw an exception with setters). AspectJ provides a much more maintainable solution without ever having to go near something like ASM.

So I’m left wondering if APT has any value to your regular Java developer (rather than toolkit developer), I don’t think it has. APT’s use-case looks purely in the space of creating extensions to the regular Java compiler to generate bye products directly related to the class with the annotation.

As a general rule I’d break down APT and AspectJ usage as follows:

  • Use AspectJ if you need to add a functional requirement to existing entities. Examples include: monitoring, architecture enforcement, transactional functionality.
  • Use APT if you need to generate bye products for framework integration. Examples include: schema generation, source code generation tools (e.g. JAXB, JAXWS)

APT is not designed to be updating code to meet a functional requirement, AspectJ is. Instead APT provides a compiler extension that allows you to generate bye products driven by meta data on a class.

java , ,

JUploader: A simple Flickr photo uploader for Linux

January 2nd, 2009

JUploader is a Java based tool for uploading photos to Flickr. It is platform specific due to a dependency on Eclipse’s SWT. I’ve been running it on Ubuntu (8.10, AMD64 architecture) without any issues.

Key features include:

  • Drag and drop mass upload of photos to Flickr account.
  • New album creation before uploading.
  • Resizing of photos before uploading.
  • Rotation of photos before uploading.

It’s a simple tool that does the basics you need before uploading photos to flickr: http://juploadr.org.

tools ,