É possível recuperar a expressão lambda em tempo de execução

Eu estava brincando com Java8 Lambda ontem à noite e eu queria saber se é possível recuperar a expressão Lambda em tempo de execução. Em suma, e tanto quanto eu entendi, a expressão Lambda é convertida em methods (estáticos) em tempo de execução e, em seguida, chamada usando InvokeDynamics.

Vamos dar um exemplo como este:

people.filter(person -> person.getAge() >= minAge); 

em que filter seria um método personalizado usando um Predicate como parâmetro. Dentro desse método de filter , como eu poderia recuperar o argumento em um formulário similar (ou idêntico) à expressão do Lambda ( person -> person.getAge() >= minAge ) nesse caso?

Tentei ler o bytecode gerado da class do argumento usando ASM5_BETA, mas não consegui ir além de usar um ClassVisitor e um MethodVisitor para alcançar o método associado à expressão do Lambda.

 public  List filter(Filter expression) { try { Class expressionClass = expression.getClass(); byte[] content = getClassContent(expressionClass); ClassReader classReader = new ClassReader(content); classReader.accept(new PredicateClassVisitor(), 0); } catch (Throwable e) { e.printStackTrace(); } return null; } private byte[] getClassContent(Class expressionClazz) throws IOException { InputStream stream = Thread.currentThread().getContextClassLoader() .getResourceAsStream(getClassName(expressionClazz.getName())); return IOUtils.toByteArray(stream); } private String getClassName(String expressionClazz) { return expressionClazz.substring(0, expressionClazz.indexOf('$')) .replace('.', '/') + ".class"; } static class PredicateClassVisitor extends ClassVisitor { public PredicateClassVisitor() { super(Opcodes.ASM4); } @Override public MethodVisitor visitMethod(int i, String s, String s2, String s3, String[] strings) { return new PredicateMethodVisitor(); } } static class PredicateMethodVisitor extends MethodVisitor { public PredicateMethodVisitor() { super(Opcodes.ASM4); } @Override public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { for (Object object : bsmArgs) { System.out.println(" " + object.toString()); } } } 

Eu não tenho certeza se este é o caminho certo a seguir, e eu queria saber se havia ferramentas mais apropriadas no ASM ou no JDK8 para tal propósito.

Obrigado por qualquer conselho 😉 Atenciosamente, Xavier

Você já sabe que as expressões lambda são geralmente compiladas em um método sintético, então você já sabe qual código descompilar para obter o código-fonte do lambda ou, bem, algo semelhante ao código original ou mesmo algo completamente diferente, dependendo do código específico .

Não há razão para que descompilar expressões lambda seja mais fácil do que descompilar qualquer outra expressão Java. Expressões simples podem ser fáceis de recuperar, especialmente quando o código possui informações de debugging, é muito provável que expressões complexas pareçam diferentes quando decompilar, especialmente quando o compilador aplica otimizações ao código.

Você pode fazer isso em alguns casos com o Groovy, se isso puder ajudá-lo: Obtendo o conteúdo do fechamento, em groovy . A Geb realmente usa esse recurso para destacar um erro de asserção dentro de uma expressão avaliada.