Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tool to look for incompatabilities in method signatures / fields

I would like to be able to compare two versions of a class / library to determine whether there have been any changes that might break code that calls it. For example consider some class Foo that has a method in version a:

public String readWidget(Object widget, Object helper);

and in version b the method becomes:

public String readWidget(Object widget); //removed unnecessary helper object

or something similar in the case of a field:

version a: public static Object sharedFoo;
version b: static Object sharedFoo; //moved to package private for version b

I would like a tool that will flag these changes as potential incompatibilities (but ideally not the reverse i.e. increasing the visibility of a method). Now I know that I can do this via reflections, or by analyzing the output from javap, however it seems like there should be an existing tool (preferably non-commercial). So I wanted to see if anyone can recommend something before I make the mistake of rolling my own / reinventing the wheel unnecessarily.

like image 396
M. Jessup Avatar asked Mar 24 '11 12:03

M. Jessup


3 Answers

I might not be understanding the question, but isn't the compiler the exact tool that would solve this problem?

Re-compiling the classes that use Foo against the new version of Foo will illuminate very quickly if there are any incompatibilities.

like image 102
matt b Avatar answered Sep 21 '22 06:09

matt b


Guava uses JDiff to report version changes, maybe you can find it useful, too?

like image 37
mindas Avatar answered Sep 20 '22 06:09

mindas


Here's the answer you didn't want, but I think it's a valid answer:

  1. Write a suite of unit tests that invoke every single method of your API (you already have this, right? :-)).
  2. When you make an API change, recompile the new version of your API but not the unit tests.
  3. Run the "stale" set of unit tests against the "fresh" API. This stale set of tests become a canary, mimicking the situation that clients of your API would be in.

The first problem with just recompiling all client code is that it might not be possible. The code might not belong to you; it might be custom code that one of your customers has written and is not available to you.

The second problem with just recompiling client code is that sometimes, you won't even get a compilation error because the calling code doesn't need to be changed. I ran into a problem like this once. I had an API method like this:

public void doSomething(){
}

with code that linked against it. I wanted to change it to this:

public boolean doSomething() {
}

So I did so and recompiled. There were no errors, because the code that called the first version of doSomething() silently relinked to the new version (discarding the return value, which is valid in Java). Little did I know, however, that it did change the bytecode of the external class when I recompiled. We started to get errors where the API was updated but the code using it wasn't recompiled.

So instead of looking for errors, I should have also been looking at which external files had their bytecode changed as a result. At that point, I'd say you should just be using unit tests for this purpose since you should be writing them anyhow.

like image 24
Mark Peters Avatar answered Sep 22 '22 06:09

Mark Peters