Re: Strange observation: MethodHandle.invokeWithArguments() would not work, whereas Method.invoke() would with the very same arguments

2018-03-08 Thread Rony G. Flatscher
Hmm, I ran into another such problem, where using core reflection invoke(...) 
succeeds whereas using
MethodHandle.invokeWithArguments(...) does not.

The problem is also linked to the resulting object from Arrays.asList(T... a), 
this time in the
context of a stream example causing a list that contains a single String array, 
instead of a list
that contains the String array elements as its individual list elements.

Here is the ooRexx code (the tilde '~' is the explicit message operator, Rexx 
is caseless and
dynamically typed), which was originally transcribed 1:1 from a Java example 
and which works with
core reflection:

-- define a Rexx string containing letter 'k' in some of its words 
wordstring="Just a bunch of
words to test for killer items containing a k" -- turn Rexx-string into a 
Java-string: this
allows us to use Java's String methods 
refWordString=.bsf~new("java.lang.String", wordstring) --
convert the Java string into a Java List (a Collection):
alist=bsf.loadClass("java.util.Arrays")~asList(refWordString~split(" ")) -- 
create a RexxProxy
of our Worker class which implements the two functional interface -- 
methods that we use
rexxWorker=BsfCreateRexxProxy(.worker~new, , "java.util.function.Predicate",
"java.util.function.Consumer") -- now run a filter stream operation on the 
list -- (the filter
just selects words containing the letter 'k' or 'K') 
sa=alist~stream~filter(rexxWorker)~toArray
-- "filter" employs the Predicate interface -- print the results for 
verification: loop y over
sa say y end say "---" - now run a foreach operation on 
a stream -- the
consumer here just prints inputs with some surrounding brackets 
alist~stream~foreach(rexxWorker)
-- "forEach" employs the Consumer interface ::requires BSF.CLS -- get 
access to the Java bridge
::class Worker -- define Rexx class that implements the functional methods 
-- implements the
interface java.util.function.Predicate ::method test -- will return .true 
for strings containing
'k' or 'K', .false else use arg s -- fetch argument (from Java) return 
s~caselessPos('k')>0 --
implements the interface java.util.function.Consumer ::method accept -- 
will show each string
use arg s -- fetch argument (from Java) say ">>"s"<<" -- show argument

The solution here was the same as already described earlier: in order to use
MethodHandle.invokeWithArguments() do not use the result of 
Arrays.asList(array) and apply stream()
on it , but rather create the stream directly with Arrays.stream(array) each 
time a stream is needed.

It is as if the object returned by Arrays.asList(...) is being handled 
differently if using the core
reflection invoke(...) compared to using MethodHandle.invokeWithArguments(...) 
for unknown reasons
(the arguments are processed the same in both cases).

---rony


On 04.03.2018 19:05, Rony G. Flatscher wrote:
>
> 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@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)" ) 

Re: Strange observation: MethodHandle.invokeWithArguments() would not work, whereas Method.invoke() would with the very same arguments

2018-03-04 Thread Rony G. Flatscher
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@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 > > 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
> 

Re: Strange observation: MethodHandle.invokeWithArguments() would not work, whereas Method.invoke() would with the very same arguments

2018-03-03 Thread Rony G. Flatscher
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  > 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! 


___
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev


Re: Strange observation: MethodHandle.invokeWithArguments() would not work, whereas Method.invoke() would with the very same arguments

2018-03-01 Thread John Rose
On Feb 12, 2018, at 11:59 AM, Rony G. Flatscher  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.

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.

Regards,
— John




___
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev