A story about who actually writes your code. And it's not you.

I came across a very interesting situation where I found out that I'm not the only one who actually “writes” the code. But first things first.

You all know that Java code you are writing is not executed directly by the CPU. Instead there is a virtual machine (so called JVM) that executes byte-code. To get the byte code the Java code (or better known as source code) is compiled into byte-code. The byte-code is than interpreted by the JVM and executed by the CPU.

That add’s a layer of abstraction between the CPU and the compiled code, but that seems OK nowadays. Computers have gotten very fast and the JVM a de-facto standard, so that many CPU’s can execute the byte-code more or less directly, without the need of much interpretation. But it’s getting more interesting when you find yourself in a situation when the code you wrote is not longer executable. Let me explain:

Due to legal reasons we are not allowed to change certain parts of the application. The keep things separated, we pushed the untouchable parts to an individual JAR (let’s call it legal.jar). The legal.jar is send to the authorities and once they give their “go” we are allowed to use it in production. To avoid someone changing parts of the legal.jar sources, we use a j-unit test, that basically reads all files from the project folder and creates a single hash value. That hash value is than used to check if something has changed.

So the current situation is that we have an application version 1 with and a legal.jar version 1.

We kept developing on the application code and, because we are good developers, we cleaned up some old, nasty-looking code parts. So we came up with a new application (version 2), that still used the good, old legal.jar V1

Our tests were successful. So we gave it full of hope the the test department. But it didn’t take long for them to see, that the application was not working at all. Instead we could find this log message here:

java.lang.NoSuchMethodError: de.kaiheinz.MyLegalClass.myLegalMethod(Lde/kaiheinz/MyAppInterface;)V

So what happened? After an analysis, we found that a class, or to be precise a method, in legal.jar called a method from the application code:

And than we saw what has happened. The code that that called myAppMethod(MyAppInterface) looked like this in the legal.jar:

public void myLegalMethod(MyAppClass myAppClass) {
  MyAppInterface appInterface = ...;
  ...
  myAppClass.myAppMethod(appInterface);
  ...
}

That wasn’t changed. Which was secured by the j-unit test. But the code around it in the application did change. And if you have a sharp eye, you might have already seen it. The myLegalMethod tries to call a method myAppMethod with one parameter object of type MyAppInterface. However, the application doesn’t accept this parameter type anymore. It want’s a MyAppImpl type in version 2.

Wow, that was a tough one. And because we went down, the implementation ladder, changing the Interface type to the App type, there was no chance that any Java In time compiler or whatever could jump in tp help. Therefore we got the exception.

But one question remains: Why didn’t we notice it during build time? The answer lies in the compile phase. Before, everthing was compiled in verision 1. That means the application code was compiled, and the legal.jar was compiled at the same time. And once we came to version 2, again everything was compiled against, the newest source codes. But, and here comes the catch. The test department was aware of the fact that only the certified legal.jar is allowed in production. So they took the whole release packege, deleted the delivered legal.jar and replaced it with the official one. But this one was compiled against v1 and the compiler created a method call to “myAppMethod(MyAppInterface)”. In the new release the compiler saw, that there wasn’t any longer this method available, so it changed the type from MyAppInterface to MyAppImpl within the legal.jar. So running it all together was not a problom. But using legal.jar v1 was not possible any longer.

This was the first time for me that I should really take the compiler into thinking and does not blindly rely on it to work.

In fact, the main credits have to go to the test department, they were so clever to change the legal.jar, that we were able to see the error in the first place.

And if you wonder how we fixed it. That wasn’t so hard. We just changed the paramter type in the application back to MyAppInterface and everything was working smoothly.