1

I am debugging Java code, called from Matlab and getting an exception:

Java exception occurred:
java.lang.NoSuchMethodError: java.util.concurrent.ConcurrentHashMap.keySet()Ljava/util/concurrent/ConcurrentHashMap$KeySetView;

how can it be, that library class has no library method?

UPDATE

Matlab is using Java7. The code I call was compiled for Java8 and contains syntax

for (Tag t : matrix.keySet()) {

i.e. Java8-specific. Although, it is claimed, that it should be binary compatible with Java7, otherwise there was no sense to do many of compromises in Java8.

Dims
  • 47,675
  • 117
  • 331
  • 600
  • 1
    What version of Java are you running? At first glance it looks like Matlab is expecting the Java 8 version but you might be running 7. – Zircon Dec 15 '17 at 16:50
  • but the keySet() method has existed for the ConcurrentHashMap since Java 6... I just checked 6, 7, 8 and they all have the method keySet()... @Zircon – RAZ_Muh_Taz Dec 15 '17 at 16:52
  • 4
    @Raz_Muh_Taz true, but in Java 7 `keySet` returns a `Set` per its signature while in Java 8 it returns `ConcurrentHashMap.KeySetView`. – Zircon Dec 15 '17 at 16:56
  • @Zircon but isn't it claimed, that `Java8` code is binary compatible with `Java7`? Here we see, that I can't use `Java8` jar in `Java7` machine. – Dims Dec 15 '17 at 17:47
  • 1
    @Dmis You can use `Java7` code in `Java8` machine, but not `Java8` code in `Java7` machine. https://stackoverflow.com/questions/4692626/is-jdk-upward-or-backward-compatible – Adam Siemion Dec 15 '17 at 17:59
  • 3
    @Dims What makes you expect you can take code compiled against Java 8, and expect all the methods that were present in Java 8 to be present in Java 1.0? That's not how compatible evolution works. You can safely go _forward_ in time -- great care is taken to make sure this is true -- but not _backwards_. – Brian Goetz Dec 15 '17 at 18:58
  • @AdamSiemion then why didn't they do many things, like, runtime generics? It was approved by backwards binary compatibility. – Dims Dec 15 '17 at 19:09
  • @BrianGoetz what is used, is just for-each loop. It should be compiled awayand work in previous Java, why not? – Dims Dec 15 '17 at 19:10
  • @Dims you compiled the for loop using Java 8, put in a jar and then tried to execute in the Java 7 machine? – Adam Siemion Dec 15 '17 at 21:34
  • 1
    See my answer [here](https://stackoverflow.com/a/25705596/1441122). – Stuart Marks Dec 16 '17 at 20:35

1 Answers1

4

In Java 8 the ConcurrentHashMap.keySet() return type has been changed. In Oracle JDK 7:

public Set<K> keySet() {
    Set<K> ks = keySet;
    return (ks != null) ? ks : (keySet = new KeySet());
}

while in Oracle JDK 8:

public KeySetView<K,V> keySet() {
    KeySetView<K,V> ks;
    return (ks = keySet) != null ? ks : (keySet = new KeySetView<K,V>(this, null));
}

public static class KeySetView<K,V> extends CollectionView<K,V,K>
    implements Set<K>, java.io.Serializable {
Adam Siemion
  • 15,569
  • 7
  • 58
  • 92
  • So, `Java` is not portable from `1.7` to `1.8`? – Dims Dec 15 '17 at 17:38
  • 7
    @Dims This is a perfectly compatible change. `KeySetView` extends (is-a) `Set`. That makes the implementation of `keySet()` in `ConcurrentHashMap` a _covariant override_ of `keySet()` in `Map`. And the change from returning `Set` to the more refined `KeySetView` is both a binary- and source-compatible change. Code written or compiled against the 7 libraries will still work on 8. – Brian Goetz Dec 15 '17 at 18:55
  • @BrianGoetz what coolness and compatibility is it, if it does not work? There was no sense to use "covariant override" or any other things. They could just rename method completely and change both arguments and result types completely: the effect would be same - not working. – Dims Dec 15 '17 at 19:12
  • 1
    See my answer [here](https://stackoverflow.com/a/25705596/1441122). – Stuart Marks Dec 16 '17 at 20:35
  • 1
    I have discovered that even if you write `Set chunks = wrap.chunksAddPlayer.keySet();` (note that the code is compatible with Java 7) and compile with Java 8, it will convert to the `KeySetView` during compilation, which means you won't be able to use it in Java 7. – Joehot200 Jan 02 '19 at 21:15