Strange observation: MethodHandle.invokeWithArguments() would not work, whereas Method.invoke() would with the very same arguments
Rony G. Flatscher
Rony.Flatscher at wu.ac.at
Sun Mar 4 18:05:56 UTC 2018
OK, went back to do the changes (making sure to cast invokeWithArguments(...) to (Object[]) and
discovered that I forgot a hard-coded override to use core reflection in all cases.
Removing that hard-coded flag to use MethodHandles instead made the problem reappear, so I once more
went after it in the past hours and think I can now explain this more exact: the case in question is
a sequence of the following (transcribed to Java) statements that are executed in the BSF4ooRexx
bridge on behalf of the Rexx program (which itself was transcribed from a Java example found on the
Internet):
* "javafx.collections.FXCollections.observableArrayList()" returns an object that implements the
interface "javafx.collections.ObservableList", actually an instance of the non-exported
"com.sun.javafx.collections.ObservableListWrapper" class,
* a String array of month names gets turned into an ArrayList using
"java.util.Arrays.asList(monthNames)" returning listOfMonthNames (a "java.util.Arrays$ArrayList")
* "ObservableList.addAll(listOfMonthNames)" gets invoked,
* supplying the resulting ObservableListWrapper as an argument to
"javafx.scene.chart.CategoryAxis.setCategories(javafx.collections.ObservableList)" works when
invoked via core reflection, but causes an exception if invoked via a MethodHandle (the
exception being: "java.lang.ClassCastException: java.base/[Ljava.lang.String; cannot be cast to
java.base/java.lang.String")!
The problem, it turns out is the use of "addAll(listOfMonthNames)" which causes the ObservableList
to contain a single list member "java.util.Arrays$ArrayList at xxx" (toString() yielding
"[Ljava.lang.String;@yyy"). The core reflection invocations work without an error, the
MethodHandle.invokeWithArguments(...) version causes the above exception.
Changing the code to use the String array monthNames (not its list version) as an argument (hence:
"ObservableList.addAll(monthNames)" ) makes it run with both, the core reflection and the
MethodHandle invocation versions.
---rony
On 03.03.2018 19:02, Rony G. Flatscher wrote:
> John, thank you very much for your kind reply and hints!
>
> On 02.03.2018 02:47, John Rose wrote:
>> On Feb 12, 2018, at 11:59 AM, Rony G. Flatscher <Rony.Flatscher at wu.ac.at
>> <mailto:Rony.Flatscher at wu.ac.at>> wrote:
>>>
>>> While testing a rather complex one (an adaption of the JavaFX address book example enhanced with a
>>> BarChart, [1]), that exhibits a very strange behavior: when setting the values for the CategoryAxis
>>> supplying an ObservableList of the month names in the current Locale, using a MethodHandle and
>>> invoking it with invokeWithArguments() would yield (debug output):
>>
>> I just happened to see your message about your adventures with method handle:
>>
>> http://mail.openjdk.java.net/pipermail/jigsaw-dev/2018-February/013603.html
>>
>> This isn't really a jigsaw question, so I'm replying to mlvm-dev.
> Yes, I just was not sure where to post such an e-mail (as on jigsaw MethodHandle's were suggested
> I posted it there).
>
>> It looks like you are mixing or interconverting arrays of strings
>> with lists of strings. The print statements and CCE show that
>> you are passing an array of strings into a place which expects
>> a single string, and the print statements suggest you are
>> in fact passing a list containing a string array into a place
>> which expects a list of strings. Either way there are too
>> many brackets in your actual argument.
>>
>> The prime suspect when the number of brackets is off by one
>> is varargs. You code might be failing because of surprises
>> in the overload resolution of invokeWA, which accepts
>> a varargs Object array *and* a single List.
>>
>> Is your runtime invoke mechanism treating invokeWA as an ordinary
>> method? It is rather extraordinary, and may warrant a second look.
>>
>> String str;
>> Object obj;
>> Object[] aobj;
>> String[] astr;
>> List lst;
>>
>> plain single arity invocations:
>>
>> 1 mh.invokeWithArguments(str) => new Object[] { str }
>> 2 mh.invokeWithArguments(obj) => new Object[] { obj }
>>
>> and yet:
>>
>> 3 mh.invokeWithArguments(aobj) => aobj (multiple args)
>> 4 mh.invokeWithArguments(astr) => astr (multiple args again!)
>> 5 mh.invokeWithArguments(lst) => lst.toArray() (multiple args again!)
>>
>> but again, a cast removes varargs:
>>
>> 6 mh.invokeWithArguments((Object) aobj) => new Object[] { aobj }
>> 7 mh.invokeWithArguments((Object) astr) => new Object[] { astr }
>> 8 mh.invokeWithArguments((Object) lst) => new Object[] { lst }
>>
>> Your bug looks like a confusion between two of these,
>> perhaps 5 and 8.
> The invocation occurs with an aobj kind of argument (an array of coerced arguments matching the
> types of the parameterTypes array), defined as "Object [] coercedArgs=..."); nevertheless will
> make sure to cast explicitly everywhere invokeWithArguments() gets used (there are
> MethodHandle.invoke(...) as well, which I will replace with invokeWithArguments instead, just to
> have everything use the same invocation method consistently in case arguments need to be supplied;
> also foregoing bindTo().invoke(...), replacing it with appropriate invokeWithArguments() for
> consistency).
>
> ---rony
>
> P.S.: After having rewritten the Java reflection (adding caching of Field, Method, Constructor
> objects together with their corresponding MethodHandle objects) part I also rewrote some of the
> core ooRexx/C++/JNI stuff to remove old-standing (18+ years) code with modern ooRexx-4.x-API code,
> which allows to forgo many of the old restrictions, and improving speed in those corners as well
> (still some cleanup to do). After getting the test units to pass, I turned to this application,
> and that problem using MethodHandle invocations only does not surface anymore!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/mlvm-dev/attachments/20180304/624417de/attachment.html>
More information about the mlvm-dev
mailing list