10

Recently, we upgrade the Jdk version from 1.6 to 1.8 in one of my Java project. But there are some compilation or runtime errors, so I have to upgrade some libraries:

  • gradle: 1.9 to 1.10
  • spring: 3.x to 4.x

That because they are using some early versions of ASM, but which supports jdk 1.8 only from 5.x

Java said it is backward compatible, but why the original versions of libraries can't work with jdk 1.8 directly?

Sergey Ponomarev
  • 2,947
  • 1
  • 33
  • 43
Freewind
  • 193,756
  • 157
  • 432
  • 708
  • 7
    Java 8 bytecode will not run on a Java 6 JVM - that's not what backwards compatibility means. In the same way, Java 8 bytecode can't be processed by a library designed for Java 6 bytecode. – user253751 Jan 30 '15 at 02:54
  • @immibis as per [this question](http://stackoverflow.com/questions/16143684/can-java-8-code-be-compiled-to-run-on-java-7-jvm), Java 8 introduces no new bytecode. The difference lies in another part – phuclv Jan 30 '15 at 04:02
  • 4
    @LưuVĩnhPhúc there are no new *instructions*, but that doesn't mean the bytecode format hasn't changed (and it has!) – user253751 Jan 30 '15 at 04:04
  • 3
    In straightforward terms, the ASM library deliberately and openly fails to comply with the prerequisites which the code must meet for binary compatibility guarantees to apply. – Marko Topolnik Jan 30 '15 at 08:46
  • 2
    @Lưu Vĩnh Phúc: it depends what you mean with the colloquial term “bytecode”. There are no new instructions, but the class file format has changed. – Holger Jan 30 '15 at 09:11
  • @Holger Do you have any details about changes in classfile format between Java 7 and Java 8? Any reference? – Rogério May 05 '15 at 18:56
  • 1
    @Rogério: Well, `interface`s can have non-`abstract` (including `static` and `private`) methods now, which also affects the rules about the combination of `invoke…` instructions and their target types. Further, there are new attributes like `Runtime[V|Inv]isibleTypeAnnotations` and `MethodParameters`. The best source is, of course, the [The Java® Virtual Machine Specification](http://docs.oracle.com/javase/specs/jvms/se8/html/index.html) – Holger May 05 '15 at 19:12
  • @Holger Ok, but apparently there were no changes in the class file format, from what I can see. – Rogério May 05 '15 at 21:47
  • 3
    @Rogério: depends on what you mean with “class file format”. The general structure hasn’t changed, there are only a new version number, new attributes and new definitions about what constructs are allowed/may appear at which places. That’s enough to make certain existing byte code parsing tools crash and that’s what the discussion was about. As a side note, even the fact that javac now *uses* the `invokedynamic` instruction, which isn’t a new Java 8 feature but unused in ordinary Java 7 code, caused several tools working with Java 7 code to fail on Java 8 code. – Holger May 06 '15 at 09:18

2 Answers2

13

ASM is a pretty low-level library.

It processes Java byte-code directly (whereas a "normal" application would just let the JVM load its classes). The byte-code format changes from time to time, and newer versions cannot be used by an older JVM.

Messing with JDK or class format internals is not covered by backwards compatibility.

This is really an edge-case, and ASM is pretty much the only "popular" example.


More importantly (and more common) though are slight behavioural changes in system library code. So your application will technically still run, but do things differently. Most of the time, you want that, as it means improvement (for example better performance), but sometimes it can cause bugs for you.

For example:


But all-in-all the legacy app compatibility story is really good with Java. They have to keep it in mind with all their enterprise customers.

Community
  • 1
  • 1
Thilo
  • 257,207
  • 101
  • 511
  • 656
  • 2
    • Updating the Unicode version may change character properties (which may change the result of `toUpperCase()` or case insensitive sorting, etc.) – Holger Jan 30 '15 at 09:08
  • Thanks for your comment. Could you give more info about incorrct implemented Comparators? Also I tried to grow all migration issues in one place https://stokito.wordpress.com/2015/07/28/linkset-migration-to-java-8/ – Sergey Ponomarev Aug 10 '15 at 16:19
  • 2
    @stokito: I added a link. http://stackoverflow.com/questions/11441666/java-error-comparison-method-violates-its-general-contract – Thilo Aug 11 '15 at 02:52
  • 2
    Nice list. There are many more incompatibilities in Java-8. [Changes in generics compilation](http://stackoverflow.com/q/30087751/4856258), [inability to extend BitSet and implement Set due to new default methods](http://stackoverflow.com/q/30445516/4856258), [changes in rounding behavior](http://stackoverflow.com/q/30778927/4856258) are just few examples I remembered. – Tagir Valeev Aug 11 '15 at 05:54
11

Because ASM is a tool that operates on the Java byte-code. And the byte-code format changed to introduce new features. As such, you had to upgrade the tool to support the new byte-code.

Note, that software compiled with an older version of the JDK does not always work with newer versions of Java. For example, enum was not a keyword in early versions of the JDK.

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • 6
    About the `enum` keyword: That seems to only affect the compiler. If I had old code compiled with an `enum` class or field or method of my own, shouldn't it still work? It certainly should not have any effect if I used the new keyword as a local variable or parameter name. – Thilo Jan 30 '15 at 03:00
  • Could you explain something for the special needs portion of the class? If `enum` was in a certain JDK (Java 5, I believe), then it wouldn't be *expected* to work on JDK 4, correct? I don't get the connection. – asteri Jan 30 '15 at 03:02
  • 2
    @asteri: It is a keyword now. Before that, you could name your own things (classes, variables, methods) `enum`. Now you cannot anymore. As I result, the same code does not compile anymore with the new compiler (I am still dubious that it affects the runtime). – Thilo Jan 30 '15 at 03:04
  • 1
    @Thilo It wasn't common, but yes. A reference named `enum` was made illegal after Java 1.4; and thus the code compiled with Java 1.4 in that case would not work with Java 5+. – Elliott Frisch Jan 30 '15 at 03:05
  • 3
    Sure it does. Compile this with `-source 1.4`. Still runs on Java7: `public class enum{ public static void main(String[] argv){ System.out.println(1); } }` – Thilo Jan 30 '15 at 03:10
  • 1
    @Thilo Now compile another class with `-source 1.5` and try to use it. :) I had to rewrite 20 lines of code about 8 years ago... it wasn't spectacularly hard. – Elliott Frisch Jan 30 '15 at 03:11
  • 5
    You said "software compiled with an older version of the JDK " and later clarified "thus the code compiled with Java 1.4 in that case would not work with Java 5+.". Of course, you cannot compile against it properly anymore, but it still runs. Binary compatibility for unchanged legacy applications. – Thilo Jan 30 '15 at 03:12
  • 1
    @Thilo There were some other issues, if your code used reflection. Not that it was very common and I can't really recall 100% of the details. – Elliott Frisch Jan 30 '15 at 03:13
  • 1
    Another issue I ran into is XML parsers and API. They started bundling them with the JDK at one point, and that broke a few things (which you could work around by some startup properties). And then there is the "inconsistent comparator" exception you get from newer JDK Collections.sort (if you had a bad comparator). Someone should make a list. – Thilo Jan 30 '15 at 03:16
  • 5
    @Thilo Failing with an exception against code violating its contract does not count as binary incompatibilty, though---the code's behavior was *undefined* to begin with. They made `Thread#stop(Throwable)` fail with `UnsupportedOperationException`---I think that's the strongest example yet of breaking binary compatibility. – Marko Topolnik Jan 30 '15 at 08:42
  • 2
    Code which compiled and worked before Java 5 and doesn’t compile anymore: `Arrays.sort(new Object[]{"foo","bar"}, String.CASE_INSENSITIVE_ORDER);` – Holger Jan 30 '15 at 09:04