arrayLength argument of MethodHandle.asCollector() and failing JCK test 'asCollectorIAE01'

John Rose john.r.rose at oracle.com
Fri Jun 28 14:03:24 PDT 2013


Volker, sorry about the delay in clearing up this report.

You are right that the test is wrong.  Your test contains an unreached code which is also in error, since method handles cannot have arity of exactly 255.

I just filed another bug to clarify the spec, 8019417.  Description:

The specification for MethodHandle guarantees that each method handle has a method called invokeExact (and also invoke): 
 * A method handle contains a pair of special invoker methods 
 * called {@link #invokeExact invokeExact} and {@link #invoke invoke}. 

Because of JVM limits on the arity of methods, any non-static method can take at most 254 arguments, for total argument count (including receiver) of 255. The limit is lower if there are doubles or longs. 

Therefore, a method handle's invokeExact method, and hence its type, cannot have an arity larger than 254. 

It is therefore impossible to: 

* lookup (reify as a method handle) a static method with arity 255 
* create a dropArguments or permuteArguments transform which increases the resulting arity to 255 
* create a collector transform which collects zero arguments and increases the resulting arity to 255 
* request an asType or explicitCastArguments conversion of a method handle to a type of arity 255 
* create an exactInvoker or generic invoker for method handles with arity 254 
* create a spreadInvoker for method handles with arity 254 which spreads less than two arguments 

All of these attempts throw (or should throw) IllegalArgumentException. 

For example, since MethodHandles.exactInvoker produces a method handle which invokes its first argument, it follows that the exact invoker's argument can have an arity of no more than 253. I.e., you cannot make an exactInvoker (or generic invoker) for a method handle type with a maximal arity of 254. 

It is theoretically possible to delay the throw by creating a "dummy" MH that refuses its inputs, but the 292 API generally has a fail-fast design in such corner cases. For example, an asType that requests an impossible conversion will throw WrongMethodTypeException, rather than deferring to a later invocation of the broken method handle. 

— John

On Apr 3, 2013, at 5:20 AM, Volker Simonis <volker.simonis at gmail.com> wrote:

> Hi John, Christian,
> 
> could you please have a quick look at this problem.
> Because of it is currently not possible to pass a Java 7 certification for a hsx24/hsx25 based VM.
> 
> Thank you and best regards,
> Volker
> 
> On Tue, Mar 26, 2013 at 1:15 PM, Volker Simonis <volker.simonis at gmail.com> wrote:
> Hi,
> 
> while running JCK test for our PPC port I realized that the test 'asCollectorIAE01' which checks valid and invalid 'arrayLength' arguments to MethodHandle.asCollector() fails for the current 7u/jdk and jdk8/jdk sources. Further investigations revealed that the failure is due to the change "7191102: nightly failures after JSR 292 lazy method handle update (round 3)" which changed the way how sun.invoke.util.ValueConversions.varargsArray() works. Apparently, the new implementation can now handle 'arrayLength' parameters up to 254 while the old implementation could only handle up to 253 parameters.
> 
> However the mentioned JCK test explicitly checks that MethodHandle.asCollector() throws an exception if called with an 'arrayLength' argument of 254 and fails for current  jdk7u and jdk8 builds because they can handle such an argument.
> 
> The API-documentation of "MethodHandle.asCollector()" is a little vague because it only states "Throws: IllegalArgumentException - if ... arrayLength is not a legal array size" but doesn't actually specify which are "legal array sizes". I therefore think that this is an implementation detail and the JCK test should not check for values like 254 but only for the real hard limits imposed by the VM (i.e. 255). I would therefore propose to exclude the mentioned test from the TCK. Otherwise the API documentation would have to be changed to explicitly specify the valid range of 'arrayLength' arguments.
> 
> Attached you can find a small test program which can be used to reproduce the problem. Running the program with a released Java 7 version (which doesn't contain the change "7191102" yet) will throw an IllegalArgumentException if MethodHandle.asCollector() is called with an 'arrayLength' argument of 254. On the other hand if the program is beeing run with a recent JDK8 build (i.e. b82) or a curent build of jdk7u, MethodHandle.asCollector() will accept 254 as 'arrayLength' parameter and the generated MethodHandle can indeed be invoked with 254 arguments.
> 
> Notice that there already exists a bug which is related to this problem: "7194534 : MethodHandle.asCollector() throws IAE with "bad parameter count 256" in spite of correct param count" (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7194534). However it only objects the fact that for the the old implementation the IllegalArgumentException wrongly reports 'arrayLength' + 2 instead of  'arrayLength' as the failing argument.
> 
> Thank you and best regards,
> Volker
> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/mlvm-dev/attachments/20130628/3176254c/attachment.html 


More information about the mlvm-dev mailing list