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"));
}
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"));
}
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));
}
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);
}
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");
}
Aggregations