Comments (10)
With version 0.7.0 japicmp now supports source compatibilty changes.
from japicmp.
Let me clarify a bit. It does indeed not break binary compatibility as defined by the JLS. But it does break source compatibility if the clients are expected to implement the interface (say for a callback).
I guess what I'm after is a way to break the build if source compatibility is broken.
from japicmp.
This will apply only to class file version 51 and earlier as Java 8 safely allows additions to interfaces if a default implementation is provided.
from japicmp.
Indeed, adding a method to an interface does not break binary compatibility. In theory this is described here in the Java Lang. Specification. And in practice it does really work. Having at runtime a new version of the interface with a new method does still executed the old code, although the class does not implement all methods from the new interface.
Source code compatibility is currently not supported.
from japicmp.
@siom79: Calling the methods that the class already implemented is not a problem, correct. But if the new method is called, it will fail at runtime with an java.lang.AbstractMethodError
for implementations that do not implement the new method.
So, in practice, ignoring this may lead to errors at runtime.
This means I can not rely on breakBuildOnBinaryIncompatibleModifications
. What I do for now is use breakBuildOnModifications
, and manually check for source compatibility. When it is compatible, I'll have to add an exclude for the newly-added method.
from japicmp.
@robinst: OK, but if you are calling the new method of the interface, then you have already upgraded to the new version, don't you? Or how does the client code know about the new method in the interface?
The breakBuildOnBinaryIncompatibleModifications
option should only check if you can run the new version of your library with applications that have been compiled against the old version. For example, your application is compiled against Google's guava in version 16.0 and now you upgrade to 16.0.1. If in 16.0.1 a new method has been added to an interface, then your application should run without any modifications.
from japicmp.
I'm sorry, I should have been more clear with my example. Let's take a real-world example:
Java 7 has a FileVisitor interface. It is used as a parameter for Files.walkFileTree.
Users of this API are expected to implement this interface and pass it as an argument to walkFileTree
. Java then calls the appropriate methods of the interface.
Now, let's say Java adds a new method foo
to the FileVisitor
interface and calls it in walkFileTree
. This would pass the check. But clients that upgrade to the new Java version would now fail at runtime.
So even though the change is binary compatible, compatibility as you define it is broken:
The
breakBuildOnBinaryIncompatibleModifications
option should only check if you can run the new version of your library with applications that have been compiled against the old version
from japicmp.
Thank you for pointing me to the exact problem. Now I can reconstruct the java.lang.AbstractMethodError
.
But this problem is hard to solve in a general form. The point is that in the case of the visitor pattern, the library under development itself calls the new method. The application compiled against an older version of this library still does not know about this new method. The exception java.lang.AbstractMethodError
is actually thrown in the library code.
On the other hand, binary compatibility in the sense of the Java Language Specification is still not broken.
What could be a solution to the problem?
- Adding source compatiblity as a new feature is hard, as it is not easy to determine, particularly in the case of wildcard imports (see this blog article written by a JDK engineer).
- Scanning the library under investigation for invocations of the new method through an interface could help to solve your particular problem, but might not be a general solution.
- Just making the addition of a method to an interface a binary incompatible change would not be aligned with the Java Language Specification.
Do you have an opinion on that?
from japicmp.
I think what would be useful is if interfaces could be marked as "to be implemented by clients" (e.g. like FileVisitor) as opposed to being implemented by the library itself. (In the Eclipse code base, the opposite is done, interfaces that should not be implemented by clients are marked as @noimplement
in Javadoc.)
Then, if an interface is marked as that, adding a new method breaks compatibility. If the interface is not marked, then adding a new method is fine (other modifications such as deleting an existing method is still a break though).
It could be done in a similar fashion to includes/excludes. Not sure how such a section should be named, maybe "implementedByClients" or something more specific, "breakOnAbstractAdditions".
from japicmp.
👍 Nice work, thanks!
from japicmp.
Related Issues (20)
- Warning or error when new API has no since tag
- CLASS_GENERIC_TEMPLATE_CHANGED on new class
- include/exclude packages without subpackages HOT 1
- java.lang.IllegalStateException: value is absent.
- Add new compatibility check METHOD_MOVED_TO_SUPERCLASS HOT 1
- CLI tool to skip checking deprecated methods
- Report doesn't show the jar it is under HOT 1
- Changes report includes unchanged properties, e.g. class file format
- Exclude unchanged classes and methods from HTML report HOT 4
- Filter for full annotations HOT 5
- >=0.16.0: Cannot compare versions because the number of old versions is different than the number of new versions HOT 4
- Move of method to superclass with generics METHOD_REMOVED HOT 1
- New default method detected as METHOD_NEW_DEFAULT when BinaryIncompatible disabled and SourceIncompatible enabled HOT 1
- htmlTitle not actually added to html file HOT 2
- Changing default method to static should be separate case HOT 5
- Switch to Apache Groovy HOT 1
- False positive when making a package-private class public that already has a public static method's different return type HOT 5
- Maven plugin does not obey property japicmp.skip when generating reports. HOT 2
- False positive when on a final class protected method made into private HOT 1
- Regression CLASS_GENERIC_TEMPLATE_CHANGED HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from japicmp.