Weird ClassCastException

Rick Bullotta rick.bullotta at thingworx.com
Tue Nov 5 06:44:53 PST 2013


I actually don't see a problem with throwing an exception in the cases where the conversion is nonsensical.  In fact, I think that is an important protection mechanism.


-----Original Message-----
From: nashorn-dev-bounces at openjdk.java.net [mailto:nashorn-dev-bounces at openjdk.java.net] On Behalf Of Attila Szegedi
Sent: Tuesday, November 05, 2013 9:32 AM
To: Tal Liron
Cc: nashorn-dev at openjdk.java.net
Subject: Re: Weird ClassCastException

I have a quite good idea what change caused this; we recently moved lots of explicit conversions into method handle signatures, e.g. instead of doing

LOAD x
INVOKEDYNAMIC "dyn:getMethod:get"
LOAD x
LDC 'test'
INVOKEDYNAMIC "dyn:call" (Object, Object, Object)Object INVOKESTATIC "toBoolean" (Object)Z

to implement "x.get('test')" as a boolean predicate for the if statement, we now do a simpler equivalent where we merge the expectation of the return type into the function invocation and thus eliminate an explicit conversion from bytecode:

LOAD x
INVOKEDYNAMIC "dyn:getMethod:get"
LOAD x
LDC 'test'
INVOKEDYNAMIC "dyn:call" (Object, Object, Object)Z

This has the advantage that when we link to Java API that already returns a boolean (think: Map.isEmpty, etc.), we can more simply link through and avoid a boxing to Object in the return value and then an unnecessary unboxing back to boolean. NB: this change is not specific to booleans and if statements, we eliminated a large amount of explicit conversions in bytecode this way.

Unfortunately, our built-in "to boolean" (and "to number" and "to string") conversions when used directly on dynamically linked Java method invocation don't apply to objects that are foreign to Nashorn. We'll happily convert a native ScriptObject or NativeArray to boolean, or even a Double or a String (as they are used internally), but we won't convert a java.io.File - a runtime-foreign object - to boolean automatically.

We could modify the system so that it performs such conversions, but if we did, then you could also pass a java.io.File to a Java API that expects a boolean parameter (potentially making overload resolution ambiguities even more aggravated, although we can mitigate that). The reason for this is that we have a generic conversion architecture in our system that works symmetrically in both directions - parameters and return types, so if you allow a conversion on a return type, then you allow it on a parameter too.

How do people feel about allowing full spectrum of Object->(String, number, boolean) conversions in both directions (both to Java and from Java)? We could also be thinking along the lines of asymmetric conversion rules - some allowed on Java parameters, some only allowed on Java return values, but it's not yet crystal clear right now to me how to fit that into the architecture (not saying it's impossible, just saying it needs more thinking on my part.) Also, some people might end up thinking such asymmetry is a bug...

Attila.

On Nov 5, 2013, at 10:17 AM, Tal Liron <tal.liron at threecrickets.com> wrote:

> OK, after some work I've managed to isolate the bug. This short program will cause the exception:
> 
> var x = new java.util.HashMap()
> x.put('test', new java.io.File('test')) if (x.get('test')) {
>  print('Found!')
> }
> 
> The issue seems to be with *casting return values of Java methods* (which should cast to boolean; I don't know why it tries to cast to a java.langNumber). Simple casting a Java object won't cause the exception.
> 
> I'll remind you that this bug appeared only in a recent commit (last few days).
> 
> On 11/05/2013 03:39 PM, A. Sundararajan wrote:
>> No, it is hard to debug with cast issue without access to code.
> 



More information about the nashorn-dev mailing list