Holger Klawitters Java "Blog"

2009-10-21: Why DSL is like operator overloading

Groovy/Grails is pretty cool, but in my opinion the design makes too heavy use of DSL.

One is supposed to use "interface by convention" (DSL #1) to implement requests to web application. Here is a controller replying to http://host/webapp/my/summary:

class MyController {
  ...
  def summary = {
     ... see below ...
  }
}

This controller is supposed to produce an xml reply, so I use DSL #2:

render( contentType: "text/xml" ) {
  entries {
    for( e in data ) {
      entry {
        text { e.content }
      }
    }
  }
}

In this case everything works as expected:

<entries><entry><text>some text</text></entry></entries> 

But in my application the element "entries" should be named "summary" which does not work. Groovy would interpret the element name as the method of the controller. The call then leads to endless recursion.

So you cannot create element names equalling to controller URIs?

Even worse, "entry" should be named "message" and I still have to figure out why this leads to omitting the element tags completely.

Moral: DSL should be used with the same care as operator overloading

2009-07-31: How to properly wait for the end

I recently had a bunch of threads each taking data from the previous one and passing data to the next. The code was roughly like this:

class Worker implements Runnable {
  public void run() {
    while( !eof() ) {
      put_to_next( alter( get_from_prev() ) );
    }
    finish();
  }
}
...
  for( int i=0; i<n; i++ ) worker[i].init();
  for( int i=0; i<n; i++ ) t[i] = new Thread( worker[i] );
  for( int i=0; i<n; i++ ) t[i].start();
  // Wait for the last worker
  t[n-1].join();

Everthing worked fine, but once in a while one of the workers behaved as if finish() had already been called when entering get_from_prev(). There, an exception was being thrown indicating that finish() had already been called. I was absolutely sure that the worker was properly initalized (init() had definitely been called!)

I was beginning to lose my faith in the memory management of the Java VM until I remembered that the workers were being reused. So the problem was that even though I waited for the last worker, the workers before were not neccessarily finished. The finish() of the previous run was being called after the init() of the next one.

The solution was simple. Waiting for the last runner is not enough, one also has to wait for the first.

  for( int i=0; i<n; i++ ) t[i].join();

2007-07-06: Constructive Fun

In a constructor the first call must be the call to the constructor of the superclass. Before that call is completed you may not assign values to instance variables. Hence the following Child is not allowed:

class Child extends Parent {
  SomeOb ob;
  public Child() {
    super( ob = new SomeOb() );
  }
}

You cannot assign to local variables either as the declararion already counts as statement.

public Child extends Parent {
  SomeOb ob;
  public Child() {
    SomeOb tmp;
    super( tmp = new SomeOb() );
    ob = tmp;
  }

If the Parent provides access to the Object you can revert to:

public Child extends Parent {
  SomeOb ob;
  public Child() {
    super( new SomeOb() );
    ob = getSomeOb();
  }
But what if there is no such call as in BufferedReader for the Reader? Don't despair, there is an easy solution! All you have is to create another constructor accepting the object to handle:

class Child extends Parent {
  SomeOb ob;
  public Child() {
    this( new SomeOb() );
  }
  private Child( SomeOb ob ) {
    super( ob );
    this.ob = ob;
  }
}

This way, by creating a new constructor you have also created a new scope in which your newly created object has a name. You can safely use this name for assigments after returning vom the super constructor.

2006-06-29: Funny quirks with Java Garbage Collection

You have to bring the garbage out, if you want to have it collected

After starting with Java I really liked the fact that I didn't have to free unused objects.

Well, there is still the need to null out references to objects you no longer need. For example, if you have a FileLoader class storing the contents of the file in an instance variable, you have to set the reference to that loader to null if you no longer need that content - or you have to write a close method in FileLoader setting the content to null.

This issue is widely known, but espacially in Java there is more! I wrote a program reading thousands of files with a total size of more then 500MB. I thought I made everything right (see above), but the program still ran out of heap space. I was baffled, the profiler told me that all content was on heap but I was sure having cleaned the content variable in the relevant loop.

What was the culprit? The program ran fine for months, only after replacing my regular expression library against another one [1] the memory consumption increased. Was the library that inefficient? Was there a memory leak? I took care that the regex patterns were being nulled, but that didn't help either.

Finally (with Java 6 (Mustang) and jhat) I found the source of the problem: Java tries some clever things with char sequences. A String does not "own" the char[] holding the actual data. Instead it stores an offset and a length into a possibly shared content, an instance of char[]. Creating a substring does not need to do a copy - you only create a new String with the appropiate offset and length into the same content.

Altough the content "String" was being reclaimed, the underlying char[] arrays were not. My program extracted some match result "groups" from the files. The old library constructed the groups somehow and hence created new Strings, whereas the new library returned true substrings. Sounds like a good idea, but in my case it bites.

Luckily Java provides a solution. The constructor String(String) creates a copy of the underlying char array [2]. All I had to do was to replace data = matcher.group(n) with data = new String(matcher.group(n)).

Annotations:

  1. The old library was the oromatcher, the new one was the java.util.regex library supplied with java since JDK 1.4.
  2. In fact, a new char[] is being created only if the new String is a true substring of the old content.

2004-10-01: Dir.jar

Isn't it stupid that a Java VM cannot change it's current directory? Well, there are some security considerations to be taken.

  • How do class loader depend on the current directory - in particular if some of the CLASSPATH components contain relative paths? (I did some testing: It seems that the class loader keeps it's own copy, so we are safe).
  • What about multi threaded Programs? (But one might still have good reasons to do so where this problem does not apply.)

Until SUN provides a clean thread safe interface to change the current directory you are welcome to use this small jar File.

It provides a JNI based access to query and change the current working directory. Just set the the directory where to put the shared library to and run the appropiate Makefile. (e.g: make -f Makefile.linux).

Currently supported are:

If you cannot download Dir.jar because your browser complains about failing security checks, press shift while clicking to bypass smart update.