Search in sources :

Example 1 with SerializedLambda

use of java.lang.invoke.SerializedLambda in project ninja by ninjaframework.

the class LambdasTest method staticMethodReference.

@Test
public void staticMethodReference() throws Exception {
    Function1<Long, String> lambda = LambdasTest::longToString;
    LambdaInfo lambdaInfo = Lambdas.reflect(lambda);
    assertThat(lambdaInfo.getKind(), is(Kind.STATIC_METHOD_REFERENCE));
    SerializedLambda serializedLambda = lambdaInfo.getSerializedLambda();
    assertThat(serializedLambda.getFunctionalInterfaceMethodName(), is("apply"));
    assertThat(serializedLambda.getImplClass().replace('/', '.'), is(LambdasTest.class.getCanonicalName()));
    assertThat(serializedLambda.getImplMethodName(), is("longToString"));
    // 6 = static method
    assertThat(serializedLambda.getImplMethodKind(), is(6));
    assertThat(serializedLambda.getCapturedArgCount(), is(0));
    // verify it can be dynamically invoked
    String value = (String) lambdaInfo.getImplementationMethod().invoke(null, 1L);
    assertThat(value, is("1"));
}
Also used : LambdaInfo(ninja.utils.Lambdas.LambdaInfo) SerializedLambda(java.lang.invoke.SerializedLambda) Test(org.junit.Test)

Example 2 with SerializedLambda

use of java.lang.invoke.SerializedLambda in project ninja by ninjaframework.

the class LambdasTest method specificInstanceMethodReference.

@Test
public void specificInstanceMethodReference() throws Exception {
    Calculator calc = new Calculator(1L);
    Function1<Long, String> lambda = calc::l2s;
    LambdaInfo lambdaInfo = Lambdas.reflect(lambda);
    assertThat(lambdaInfo.getKind(), is(Kind.SPECIFIC_INSTANCE_METHOD_REFERENCE));
    SerializedLambda serializedLambda = lambdaInfo.getSerializedLambda();
    assertThat(serializedLambda.getFunctionalInterfaceMethodName(), is("apply"));
    assertThat(serializedLambda.getImplClass().replace('/', '.').replace('$', '.'), is(Calculator.class.getCanonicalName()));
    assertThat(serializedLambda.getImplMethodName(), is("l2s"));
    assertThat(serializedLambda.getImplMethodSignature(), is("(Ljava/lang/Long;)Ljava/lang/String;"));
    // captured "this"
    assertThat(serializedLambda.getCapturedArgCount(), is(1));
    // captured "this"
    assertThat(serializedLambda.getCapturedArg(0), is(calc));
    // verify it can be dynamically invoked
    String value = (String) lambdaInfo.getFunctionalMethod().invoke(lambda, 1L);
    //String value = (String)lambda.getClass().getMethod("apply", Long.class).invoke(calc, 1L);
    assertThat(value, is("2"));
}
Also used : LambdaInfo(ninja.utils.Lambdas.LambdaInfo) SerializedLambda(java.lang.invoke.SerializedLambda) Test(org.junit.Test)

Example 3 with SerializedLambda

use of java.lang.invoke.SerializedLambda in project ninja by ninjaframework.

the class LambdasTest method anyInstanceMethodReference.

@Test
public void anyInstanceMethodReference() throws Exception {
    ControllerMethod1<LambdasTest> lambda = LambdasTest::home;
    LambdaInfo lambdaInfo = Lambdas.reflect(lambda);
    assertThat(lambdaInfo.getKind(), is(Kind.ANY_INSTANCE_METHOD_REFERENCE));
    SerializedLambda serializedLambda = lambdaInfo.getSerializedLambda();
    assertThat(serializedLambda.getFunctionalInterfaceMethodName(), is("apply"));
    assertThat(serializedLambda.getImplClass().replace('/', '.'), is(LambdasTest.class.getCanonicalName()));
    assertThat(serializedLambda.getImplMethodName(), is("home"));
    assertThat(serializedLambda.getImplMethodSignature(), is("()Lninja/Result;"));
    assertThat(serializedLambda.getCapturedArgCount(), is(0));
}
Also used : LambdaInfo(ninja.utils.Lambdas.LambdaInfo) SerializedLambda(java.lang.invoke.SerializedLambda) Test(org.junit.Test)

Example 4 with SerializedLambda

use of java.lang.invoke.SerializedLambda in project ninja by ninjaframework.

the class Lambdas method reflect.

public static LambdaInfo reflect(Object lambda) {
    Objects.requireNonNull(lambda);
    // note: this throws a runtime exception if the lambda isn't serializable
    // or if the object isn't actually a lambda (e.g. an anon class)
    SerializedLambda serializedLambda = getSerializedLambda(lambda);
    Method functionalMethod;
    try {
        functionalMethod = getMethod(lambda.getClass(), serializedLambda.getFunctionalInterfaceMethodName());
        // important: only way classes other than the creator can invoke it
        functionalMethod.setAccessible(true);
    } catch (ClassNotFoundException | NoSuchMethodException e) {
        throw new RuntimeException("Unable to getFunctionalMethod", e);
    }
    Method implementationMethod;
    try {
        implementationMethod = getImplementationMethod(serializedLambda);
    } catch (ClassNotFoundException | NoSuchMethodException e) {
        throw new RuntimeException("Unable to getImplementationMethod", e);
    }
    Kind kind;
    // https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/MethodHandleInfo.html
    int implMethodKind = serializedLambda.getImplMethodKind();
    if (implMethodKind == 6) {
        // REF_invokeStatic
        if (serializedLambda.getImplMethodName().startsWith("lambda$")) {
            kind = Kind.ANONYMOUS_METHOD_REFERENCE;
        } else {
            kind = Kind.STATIC_METHOD_REFERENCE;
        }
    } else {
        if (serializedLambda.getCapturedArgCount() > 0) {
            kind = Kind.SPECIFIC_INSTANCE_METHOD_REFERENCE;
        } else {
            kind = Kind.ANY_INSTANCE_METHOD_REFERENCE;
        }
    }
    return new LambdaInfo(lambda, kind, serializedLambda, functionalMethod, implementationMethod);
}
Also used : Method(java.lang.reflect.Method) SerializedLambda(java.lang.invoke.SerializedLambda)

Example 5 with SerializedLambda

use of java.lang.invoke.SerializedLambda in project ninja by ninjaframework.

the class Lambdas method getSerializedLambda.

/**
     * Tries to get a SerializedLambda from an Object by searching the class
     * hierarchy for a <code>writeReplace</code> method.  The lambda must
     * be serializable in order for this method to return a value.
     * @param lambda An object that is an instance of a functional interface. 
     * @return The SerializedLambda
     */
public static SerializedLambda getSerializedLambda(Object lambda) {
    Objects.requireNonNull(lambda);
    if (!(lambda instanceof java.io.Serializable)) {
        throw new IllegalArgumentException("Functional object does not implement java.io.Serializable");
    }
    for (Class<?> clazz = lambda.getClass(); clazz != null; clazz = clazz.getSuperclass()) {
        try {
            Method replaceMethod = clazz.getDeclaredMethod("writeReplace");
            replaceMethod.setAccessible(true);
            Object serializedForm = replaceMethod.invoke(lambda);
            if (serializedForm instanceof SerializedLambda) {
                return (SerializedLambda) serializedForm;
            }
        } catch (NoSuchMethodError e) {
        // fall through the loop and try the next class
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("Functional object is not a lambda");
        } catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            throw new RuntimeException("Unable to cleanly serialize lambda", e);
        }
    }
    throw new RuntimeException("writeReplace method not found");
}
Also used : Method(java.lang.reflect.Method) InvocationTargetException(java.lang.reflect.InvocationTargetException) SerializedLambda(java.lang.invoke.SerializedLambda)

Aggregations

SerializedLambda (java.lang.invoke.SerializedLambda)6 LambdaInfo (ninja.utils.Lambdas.LambdaInfo)4 Test (org.junit.Test)4 Method (java.lang.reflect.Method)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Context (ninja.Context)1