java-goodies
 

   Little things I wish for in Java

   

There are also some big things I wish for, notably Generic Classes. This page is devoted to minor little things that would take one developer less than a day to implement - but would make life with Java a whole lot easier.


                                                    Language Changes

Shorter object reference initialization syntax.

A good percentage of lines in Java programs look like this:

 SomeLongClassName foo = new SomeLongClassName(args);
This could be a static, instance, or local variable. Of course, sometimes the two class names are different. For example:
 SomeInterfaceName bar = new SomeInterfaceImplementation(args);
But the former case is so prevalent and so frustrating to type, that I propose a shortcut syntax. I rejected the C++ syntax because one design goal of the JLS is to have a visible 'new' keyword wherever objects are created.
 SomeLongClassName foo = new(args);
should be equivalent to
 SomeLongClassName foo = new SomeLongClassName(args);
Automatic dispose syntax.

C++ requires special syntax to enable automatic disposal on scope exit. For instance, the following code:

void foo() {
Bar * const p = new Bar();
doSomething();
}
does not release the resource when the scope exits. Instead, you have to use a different syntax:
void foo() {
Bar p();
doSomething();
}
Now the resource is disposed when the scope exits. The same is true in Java. If you code:
 void foo() {
final Bar p = new Bar();
doSomething();
}
then nothing is disposed when the function exits - exactly like in C++. If however, you write:
 void foo() {
final Bar p = new Bar();
try { doSomething(); }
finally { p.dispose(); }
}
then the Bar is guarranteed to be disposed - exactly like in C++.

So what's the beef? The functionality is exactly the same. I wish that the syntax for the automatic disposal case in Java were simpler - something closer to C++ syntax. In particular, I want the syntax for automatic disposal to be *shorter* than the syntax for manual disposal - not longer. What I want is some "syntactic sugar".

  1. Create a new interface, java.lang.Disposable:
     package java.lang;

    public interface Disposable {
    void dispose();
    }
  2. For any local final reference to a class that implements 'Disposable', dispose is automatically called in a finally block. For instance, given:
     class MyFiler implements Disposable {
    MyFiler(String name) { ... }
    public void dispose() { closeAll(); }
    ...
    }
    then the following:
     void foobar() {
    // notice I'm using the initialization shortcut described above
    final MyFiler filer = new("blah..blah");
    doSomething();
    // shortcut syntax not requried for 'Disposable' feature
    final MyFiler filer2 = new MyFiler("barsoap");
    doSomethingElse();
    }
    would effectively generate this:
     void foobar() {
    final MyFiler filer = new MyFiler("blah..blah");
    try {
    doSomething();
    final MyFiler filer2 = new MyFiler("barsoap");
    try {
    doSomethingElse();
    }
    finally { filer2.dispose(); }
    }
    finally { filer.dispose(); }
    }
  3. For every Disposable class, the compiler automatically generates calls to dispose() for final reference fields first and then the base class whenever they are 'Disposable'. For example, this class:
     class Soap implements Disposable {
    private final MyFiler filer = new("bar");
    public void dispose() { }
    }
    class Shampoo extends Soap {
    private final MyFiler filer2 = new("liquid");
    }
    Would generate code equivalent to:
     class Soap implements Disposable {
    private final MyFiler filer = new MyFiler("bar");
    public void dispose() {
    filer.dispose();
    }
    }
    class Shampoo extends Soap {
    private final MyFiler filer2 = new MyFiler("liquid");
    public void dispose() {
    filer2.dispose();
    super.dispose();
    }
    }
Justifications:

  1. By making a shorter syntax do automatic disposal, clients are more likely to cleanup properly. Most programmers don't bother calling Image.flush() or Graphics.dispose() until their GUI crashes enough to annoy them.

    Even if dispose() is called while a reference is retained somewhere, this does not corrupt memory (unlike C++). This feature is just syntactic sugar for a common use of try..finally.

  2. Activating this feature with the 'Disposable' tagging interface prevents changing the meaning of existing code. Even without auto-disposal, tagging a class with 'Disposable' makes it crystal clear that the object needs to disposed. Furthermore, it provides a standard name for the dispose function. Currently, it could be 'close()' or 'dispose()' or 'flush()' or 'destroy()' or ... :-(
  3. Even without compiler support, you could follow the convention proposed. By using a tagging interface such as 'Disposable', an automatic tool can check whether the convention is properly followed from either source or .class files.
  4. In the meantime, while no standardized 'Disposable' interface or auto-disposal or initilization shortcut is available, I recommend the following practice:

    Every class with external (non memory) cleanup required should implement a standard (for your company) interface (say, Disposable). Every Disposable class must provide a 'finalize()' method (separately from the dispose() method). It should check whether the instance was properly disposed, and write a log record which will be seen by a programmer whenever finalize() has to do the dispose(). This way, programmers using your class will be encouraged to use the proper try..finally syntax where needed to avoid the annoying error messages.

                                                JVM Changes

The class file format needs to support primitive arrays.

Although the language provides for initializing primitive arrays, the current implementation is a joke. A blank array is allocated, then each element is individually set to its value. The workaround is to load a resource file to initialize large primitive arrays.

Without changing the JVM, it would be an improvement if the compiler would create this resource file for you and generate code to load it.

                                                    API Changes

Make public the equivalent of "sun.io.CharToByteConverter" and "ByteToCharConverter".

In JDK 1.1 there was a public API for user defined encodings. Furthermore, certain kinds of programs can be made 4 or more times faster by keeping an instance of a Converter loaded instead of passing the encoding name as a String. This feature was taken away in JDK1.1.3! Sun promised to give it back in an improved form - but it still isn't there in Java 2. Our database driver needs to access byte encoded fields, and the performance is unusable without using the sun.io package as per the original JDK1.1 spec. The only other alternative is to roll our own converter classes - which seems silly.


Vote NOVote YES

                        Java Notes

by Stuart D. Gathman
Last updated Jan 16, 2007

I have moved the most popular items to the top of the menu.
  • TimeZone implementation with historical and leapsecond support NEW! v1.11
  • GNU Diff algorithm in Java Bug fix and setOutput for DiffPrint.
  • Fast Fourier Transform Test code and fixes.
  • Elliptic Curve cryptograhy Bug fix.
  • Posix package for Java NEW! v1.1.5p1 Supports SysV semaphore sets. Passwd fix.
  • Class Packager for Java
  • EDX User Interface Package for Java More widgets for bmsi.edx.fs.
  • A Java AWT Implementation for ASCII Terminals
  • JAR file invoker for JDK 1.1
  • Java SNA/RJE Interface Uses a standalone networked device from JBM Electronics - and no additional software.
  • Keep javac "hot" and ready to roll
  • A Formerly Embarrassing Benchmark for AIX Java
  • Obtaining JDK1.1.4GA for AIX
  • Java Wish List

  • Class Packager for Java

    If you want to deliver an application or applet with all the classes and resources it needs - and only the classes and resources it needs, then you need ZipLock.java. The Java Cannery is a similar utility with a different feature set. Here are the doc comments for ZipLock:
    This is a utility class for examining a list of class names for all of their dependencies.

    ZipLock will read each class file and search the internal structures for all references to outside classes and resources. The checks are recursive, so all classes will be examined. A list of dependencies will be returned.

    None of the java.* classes will be examined. Additional system packages may be excluded with setExcludes().

    In addition to classes, we look for other resources loaded via Class.getResource() or Class.getResourceAsStream(). If a class calls these methods, then every String constant in the class is checked to see if a file by that name exists on the CLASSPATH in the same directory as the class - in other words where getResource would find it. This heuristic only works if your resource names appear as String constants - which seems to be the case in my practice so far.

    We can optionally write all the classes and resources found to a zip or jar, or the list of files can be retrieved with getDependencies().

    @author Stuart D. Gathman Copyright (C) 1998 Business Management Systems, Inc.

    Original version Copyright (c) 1998 Karl Moss. All Rights Reserved.

    When you create a JAR file with all the classes needed for your application, the JAR file is self-contained. It can be run by putting the JAR first in the CLASSPATH and running the main class. It will not break if later version of supporting class libraries introduce incompatibilities. This is similar to the effect of statically linking an executable in a modern dynamically linked OS.

    The Object-Oriented jargon for such a self-contained application is a "Sealed System". The original name of this class, "RollCall" just didn't convey this concept. "Sealer" was too boring. We considered "Saran", but "ZipLock" seems more airtight and suggests the underlying ZIP format of JAR files as well!


    Keep javac "hot" and ready to roll

    A good portion of the time taken by the Sun javac compiler to compile your java code is spent in "startup". The JVM must load and initialize hundreds of classes and resolve references. I have created a simple "compile server" which listens for requests on a socket and invokes the compiler repeatedly. This saves about 10sec for each compile after the first on our 66Mhz AIX system. Here is the source:
  • Compile.java - the compile server. Run in the background.
  • Submit.java - a simple program to submit compile requests and display compiler output.
  • If the reduced startup time for Submit.java is still too much, you can use C++ to submit the requests: javac.cc, socket.cc, socket.h.

    A ZIP file with all of the above.


    A Formerly Embarrassing Benchmark for AIX Java

    This benchmark runs in 6.5 seconds on a 233Mhz Pentium II with MS J++. On a 300Mhz 604 with JDK1.1.4 GA, it takes 16.844 seconds (with JIT). The JIT makes little difference. There is no swapping. Profiling reveals that memory allocation is the bottleneck.

    IBM has since released JDK1.1.6 for AIX which cuts the time for this benchmark by more than half by using a per Thread cache for memory allocation and using direct memory references instead of handles. This makes AIX competitive performance-wise with the Microsoft VM - and it's not intentionally incompatible either!

    code, soya.att,soya.exs data files
    Web page of benchmark author.


    Fast Fourier Transform

    I have always been fascinated by this algorithm. Here is a Java version adapted from 'C'. It adapts well and there is nothing kludgey here.

    FFT4.java

    Here is where I got the C code: Jo Desmet, Jo's Web Page


    Obtaining JDK1.1.4GA for AIX

    IBM no longer has this release on their web site. Several people have asked for it since it is the version they have tested against and need to install at their customers - but they have lost the AIX install image!

    You must contact IBM and ask for this release. I am not allowed to redistribute our copy - an IBM lawyer told me so. Very pleasantly and politely, I might add. It is probably easier to retest your applications against the latest release - which is 1.1.6 the last I checked. If this is a problem - then don't lose your install images. Besides, GA1.1.6 for AIX is much faster than GA1.1.4.

    You need to register with IBM to gain access to their free developer area.


    Elliptic Curve Cryptography

    I have translated some public domain C source for Elliptic Curves to Java. I have further changes planned (like interfacing with java.security and making the ECPoint class immutable), but this might save you some work. New - the ECCrypt class has a stupid bug fixed, has some tests, and sign/verify now work.
  • The Java source and compiled Jar.
  • The C source and AIX binary.
  • The Lava rocks package used by the test program (C style printf).
  • The EC.jar file includes the Lava rocks classes needed to run the test program.

    GNU Diff for Java

    I have translated the GNU Diff algorithm to a Java class. The Diff class computes the differences between two Object arrays as a list of changes. This is very general purpose. Any of the options to GNU diff can be efficiently implemented as variations on how Object.equals() is implemented and how the change list is printed.

    DiffPrint now sports a setOutput() method. The DiffPrint.Base class and derivatives should really be renamed out of the empty package.

    NOTE - unified and context printing do not combine nearby changes. Perhaps this feature was added since diff-1.15, or perhaps it is a bug. I (or someone) will need to get the latest diff source and add that feature.

    Many people have asked me to change the license to LGPL. My port is based on GNU Diff, which is GPL. Until someone convinces me otherwise, I don't believe that I have the right to change the license. I have corresponded with the copyright holders of GNU Diff, and they are unwilling to change the license. Their position is that the GPL helps force companies to GPL more code in order to use existing GPL code.

    The GPL restrictions do not apply to purely dynamically loaded code (otherwise, you would be unable to run GNU diff on a proprietary OS). When I get some time, I (or anyone who beats me to it) will create a plugin API so that applications can compile against an LGPL interface, and load the GPL implementation at runtime. This will also make comparing the performance of diff algorithms very convenient. While all Java classes are dynamically loaded at runtime, directly referenced classes are also used at compile time, and thus might be considered in violation of the GPL.

  • Diff.java The Diff algorithm
  • DiffTest.java Test for bugs sumitted by users.
  • DiffPrint.java A base class for printing the change list in 'ed' style to test the algorithm. Could form the basis for a complete Java implementation of all the GNU diff comparison and output options.
  • TODO

    Publish the revised interface that simplifies doing things with elements that are the same (as opposed to the usual requirement of dealing with just those that are different).

    A TimeZone Implementation with Historical Changes and Leapseconds

    I have translated the Unix "tz" package (formerly known as "localtime") to a Java class. In addition to reading /etc/zoneinfo files and providing unix like functions such as localtime() and mktime(), it extends java.util.TimeZone providing GregorianCalendar with TimeZones that handle historical changes and leapseconds.

    The tz code and zoneinfo files are included with modern Unix systems such as BSD and Linux.

    Version 1.11 makes ZoneInfo Serializable.

    Version 1.10 uses a better default timezone for zones with erratic changes.

    Version 1.8 uses 64 bits for the unix timestamp - which unix systems are going to have to do by 2038 anyway, closes the Zoneinfo file when it is done, and removes the call to Lava Rocks.

  • ZoneInfo.java
  • The Lava rocks package formerly used by tm.toString() to format times. No longer needed for v1.8 - but a handy package.
  • The FTP distribution of the latest tz code and timezone data.
  • TODO

    Zic zoneinfo compiler. Have the compiler detect rational cycles, and extend the zoneinfo file to have a "go back N transitions" feature as suggested by Paul Eggert.

    JAR File Invoker for JDK 1.1

    In Java 2, Jar files are directly invokable with the -jar option. For instance:
    $ java -jar myapp.jar arg1 arg2
    will look at the MANIFEST attributes for the jar to find the main class, and invoke it. Here is a simple invoker written in Java to provide the same feature with JDK 1.1. It is used like this:
    $ java jar myapp.jar arg1 arg2
  • jar.java The source.
  •