Holger Klawitters Java "Blog"

2014-10-01: (Some) Java VM Checksums (update 2019-04-09 )

As Oracle does not provide signed checksums for their Java VMs, I took the time to compute the checksums of the Java VMs I've downloaded over time. (For now these are mostly 64bit Linux Full SDK gz Files)

If your sha256 checksum differs, then either you got a tampered copy or I did.

If you find this list useful, feel free to drop me a line.

VersionSHA 256 Checksum
jdk-9.0.4_linux-x64_bin.tar.gz 90c4ea877e816e3440862cfa36341bc87d05373d53389ec0f2d54d4e8c95daa2
jdk-8u202-linux-x64.tar.gz 9a5c32411a6a06e22b69c495b7975034409fa1652d03aeb8eb5b6f59fd4594e0
jdk-8u192-linux-x64.tar.gz 6d34ae147fc5564c07b913b467de1411c795e290356538f22502f28b76a323c2
jdk-8u181-linux-x64.tar.gz 1845567095bfbfebd42ed0d09397939796d05456290fb20a83c476ba09f991d3
jdk-8u172-linux-x64.tar.gz 28a00b9400b6913563553e09e8024c286b506d8523334c93ddec6c9ec7e9d346
jdk-8u161-linux-x64.tar.gz 6dbc56a0e3310b69e91bb64db63a485bd7b6a8083f08e48047276380a0e2021e
jdk-8u152-linux-x64.tar.gz 218b3b340c3f6d05d940b817d0270dfe0cfd657a636bad074dcabe0c111961bf
jdk-8u144-linux-x64.tar.gz e8a341ce566f32c3d06f6d0f0eeea9a0f434f538d22af949ae58bc86f2eeaae4
jdk-8u141-linux-x64.tar.gz 041d5218fbea6cd7e81c8c15e51d0d32911573af2ed69e066787a8dc8a39ba4f
jdk-8u121-linux-x64.tar.gz 97e30203f1aef324a07c94d9d078f5d19bb6c50e638e4492722debca588210bc
jdk-8u112-linux-x64.tar.gz 777bd7d5268408a5a94f5e366c2e43e720c6ce4fe8c59d9a71e2961e50d774a5
jdk-8u102-linux-x64.tar.gz 7cfbe0bc0391a4abe60b3e9eb2a541d2315b99b9cb3a24980e618a89229e04b7
jdk-8u92-linux-x64.tar.gz 79a3f25e9b466cb9e969d1772ea38550de320c88e9119bf8aa11ce8547c39987
jdk-8u77-linux-x64.tar.gz a47dc0962a57b27a0cc00b9f11a53dc3add40c98633ba49a2419b845e4dedf43
jdk-8u72-linux-x64.tar.gz 46e7f96271043009995f39f04a9e711cdc0cc5b6a5b67910451678a3d250ec98
jdk-8u71-linux-x64.tar.gz 9bdb947fccf31e6ad644b7c1e3c658291facf819e4560a856e4d93bd686e58a2
jdk-8u66-linux-x64.tar.gz 7e95ad5fa1c75bc65d54aaac9e9986063d0a442f39a53f77909b044cef63dc0a
jdk-8u65-linux-x64.tar.gz 88db2aacdc222c2add4d92822f528b7a2101552272db4487f33b38b0b47826e7
jdk-8u60-linux-x64.tar.gz ebe51554d2f6c617a4ae8fc9a8742276e65af01bd273e96848b262b3c05424e5
jdk-8u51-linux-x64.tar.gz d7149012cc51c2cdb8d3a1767825e0dfc36ca0419c3dae56d993cb2732cbeff1
jdk-8u45-linux-x64.tar.gz f298ca9239051dfddf8642fcc9e264f7fe5af10adb67027feb3a0ed0a1a2316d
jdk-8u31-linux-x64.tar.gz efe015e8402064bce298160538aa1c18470b78603257784ec6cd07ddfa98e437
jdk-8u25-linux-x64.tar.gz 057f660799be2307d2eefa694da9d3fce8e165807948f5bcaa04f72845d2f529
jdk-8u20-linux-x64.tar.gz 3e717622ae48af5ca7298e7797cb71d4d545238f362741a83e69c097ca055de4
jdk-8u11-linux-i586.tar.gz 3981e6fb7d35b20ac3c05ec56fb3798ac1cd872a9e968bb3d77a718af7b146d1
jdk-8u5-linux-x64.tar.gz 44901389e9fb118971534ad0f58558ba8c43f315b369117135bd6617ae631edc
jdk-8-linux-x64.tar.gz 724a880ddb40570a7066a851a621e397151e425dea19593c0ccecc49e38f1d22
jdk-7u80-linux-x64.tar.gz bad9a731639655118740bee119139c1ed019737ec802a630dd7ad7aab4309623
jdk-7u76-linux-x64.tar.gz ce8ff4fed2cd16aea432edf8e94f21ccfe29e9d4a659bbbef3551982769e0c8c
jdk-7u75-linux-x64.tar.gz 460959219b534dc23e34d77abc306e180b364069b9fc2b2265d964fa2c281610
jdk-7u72-linux-x64.tar.gz dd1d438e1b7d4b9bb5ea4659f2103b577d1568da51b53f97b736b3232eeade8e
jdk-7u67-linux-x64.tar.gz 54dd1e13edf18c64941a55da9c91210b53dc5cf48f1a8f4538c863049e346335
jdk-7u60-linux-x64.tar.gz c7232b717573b057dbe828d937ee406b7a75fbc6aba7f1de98a049cbd42c6ae8
jdk-7u55-linux-x64.tar.gz 86f8c25718801672b7289544119e7909de82bb48393b78ae89656b2561675697

The first column contains the name of the Package I've checked. You can read the SHA256 checksum in the second column.

Clicking on the SHA256 sum will give you a file containing that very checksum along with a signature you can verify (against server tampering) using my (old) public key (ID=7292C206).

Meanwhile Oracle provides SHA256 checksums on their secured Download pages for recent VMs (eg. 8u202) on their own. Even though no significant agency has access to Oracle servers, I am still providing copys for comparison :-)

2012-01-07: Java not so greedy after all

Given the following regex a|ab, which part of xaby would you expect Java to match? Hint: it's not ab as it would be for the regex ab|a.

2010-12-08: Pattern Tip of the week from geek and poke

Geek and Poke

2010-09-21: what does "final" mean (internally)?

There is a debate going on whether a local variable, which is being assigned to only once, should be declared final or not. I don't want to dig into this debate, but there undoubtedly is a case where it is perfectly useful.

class Outer {
  void somefunction() {
    final var = ...
    new Inner() {
      ... use var ...

However, that is the actual life scope of var? Does it live as long as the outer object lives? I did not find anything in the spec about it. But peeping into the code via javap -private -c "Outer$1" revealed that the compiler will pass var to the anonymous class via an invisible constructor and store var in an instance variable. I was relieved to see that Outer will not be cluttered with invisible instance variables.

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() ) );
  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

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 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)).


  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.