Romain, On 4/26/16 5:32 PM, Romain Manni-Bucau wrote: > Le 26 avr. 2016 22:27, "Christopher Schultz" <ch...@christopherschultz.net> > a écrit : >> >> Romain, >> >> On 4/25/16 11:42 AM, Romain Manni-Bucau wrote: >>> Hi guys, >>> >>> tomcat uses ConcurrentHashMap in few places and doesn't rely on >>> ConcurrentMap API (ApplicationContext IIRC for instance was the case I >>> encounter). This means if you build tomcat with java 8 and run on java > 7 it >>> is broken cause of this new KeyViewSet API used on java 8 (returned > type is >>> used for method lookup at runtime). >> >> Which method, here? The return type of a method isn't officially part of >> the method's signature. Are you saying that the Java 8 compiler will >> choose a method (from a specific interface) at compile-time that doesn't >> exist in earlier versions of Java? >> >> Can this be fixed with a cast? >> > > This is not java 8 specific. The method lookup is done using return type > too - check bytecode with javap for instance.
The *runtime* uses the return-type of a method as part of the signature for method-lookup, but javac does not. There is no way to differentiate between two methods with the same signature but different return types, so that's not a legal in Java-source. But it's perfectly legal in bytecode (e.g. if you have a bytecode assembler, you can do it... not sure if the verifier will barf or not). It appears there is a breaking API change between Java 8 and Java 7 which causes this. :( In Java 7, java.util.concurrent.ConcurrentHashMap.keySet returns Set<K> In Java 8, java.util.concurrent.ConcurrentHashMap.keySet returns HashSetView<K,V> This seems to be a oversight on the part of the API designers. > I didnt check if a cast fixes it but using a temp var should or > moving the impl typing to the interface at field level fixes it in > tomcat and no api is missing AFAIK. I checked, and using a cast does in fact fix the problem: The Java source: ((AbstractMap)chm).keySet(); yields this bytecode: 3: invokevirtual #2 // Method java/util/AbstractMap.keySet:()Ljava/util/Set; , while this Java source: chm.keySet(); yields this bytecode: 3: invokevirtual #2 // Method java/util/concurrent/ConcurrentHashMap.keySet:()Ljava/util/concurrent/ConcurrentHashMap$KeySetView; So Mark, I think this can be done using explicit casts. It would make it much cleaner for users who have extended Tomcat internal classes. The question is whether or not we should do this at all, since it's basically a problem with Java and, if the BUILDING.txt instructions are followed, then it shouldn't be a problem. -chris --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org