ANN: InvokeBinder

Charles Oliver Nutter headius at headius.com
Sat Feb 4 08:39:03 PST 2012


InvokeBinder is a small Java DSL for binding method handles *forward*
rather than *backward* from target endpoint.

https://github.com/headius/invokebinder/

I've finished mapping MethodHandles.* and Lookup.* to its API, and
have also added a couple convenience utilities like tryFinally and nop
that are hard or confusing to implement with the MethodHandles API.

I'm interested in incorporating other utilities and patterns that you
might have...feel free to submit a pull request.

Not released to Maven yet, but will be soon as 1.0.

BinderTest (https://github.com/headius/invokebinder/blob/master/src/test/java/com/headius/invoke/binder/BinderTest.java)
has several good examples but I'm particularly proud of tryFinally:

        MethodHandle post = Binder
                .from(void.class, String[].class)
                .invokeStatic(MethodHandles.lookup(),
BinderTest.class, "finallyLogic");

        MethodHandle handle = Binder
                .from(void.class, String[].class)
                .tryFinally(post)
                .invokeStatic(MethodHandles.lookup(),
BinderTest.class, "setZeroToFoo");

Which is implemented as follows:

        MethodHandle exceptionHandler = Binder
                .from(target.type().insertParameterTypes(0,
Throwable.class).changeReturnType(void.class))
                .drop(0)
                .invoke(post);

        MethodHandle rethrow = Binder
                .from(target.type().insertParameterTypes(0, Throwable.class))
                .fold(exceptionHandler)
                .drop(1, target.type().parameterCount())
                .throwException();

        target = MethodHandles.catchException(target, Throwable.class, rethrow);

        // if target returns a value, we must return it regardless of post
        MethodHandle realPost = post;
        if (target.type().returnType() != void.class) {
            // modify post to ignore return value
            MethodHandle newPost = Binder
                    .from(target.type().insertParameterTypes(0,
target.type().returnType()).changeReturnType(void.class))
                    .drop(0)
                    .invoke(post);

            // fold post into an identity chain that only returns the value
            realPost = Binder
                    .from(target.type().insertParameterTypes(0,
target.type().returnType()))
                    .fold(newPost)
                    .drop(1, target.type().parameterCount())
                    .identity();
        }

        return MethodHandles.foldArguments(realPost, target);

Which would be quite a bit more code (and more confusing) using the
MethodHandles API directly.

- Charlie


More information about the mlvm-dev mailing list