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

Reply via email to