如何在java中重新定义lambda匿名类

时间:2016-10-26 02:57:14

标签: java lambda java-8 javaagents

JDK8将lambda表达式转换为

中的匿名类
InnerClassLambdaMetafactory.spinInnerClass() {
    return UNSAFE.defineAnonymousClass(targetClass, classBytes, null);
}

我正在编写javaagent,使用asm修改classBytes(添加方法)并将其传递给defineAnonymousClass,但该方法最终会出现此匿名类的ClassNotFoundException。有什么方法可以修改匿名classBytes的内容吗?

1 个答案:

答案 0 :(得分:0)

转换匿名加载的类很棘手。您是否重新构建已经加载的代表此类的类?如果是这样,请注意Class::getName不会返回类的实际二进制名称,但会添加一个随机哈希,例如my.DefinedType/12345,您需要删除最新的数字。

此外,您不能直接从另一个类引用这些类,但您需要直接从反射API或理想情况下的方法句柄引用它们。你不能从类加载器中查找这些类,这就是它们被称为匿名的原因。

最后,在安装类文件转换器时,不会向变换器注册此类匿名类的加载。处理这些类的最简单方法是修补负责创建lambda类型的lambda元工厂。您可以使用例如允许您创建代理的Byte Buddy轻松完成此操作:

new AgentBuilder.Default()
  .with(LambdaTransformationStrategy.ENABLED)
  .type(someMatcher)
  .transform(someTransformer)
  .installOn(instrumentation);

调用此内容,Byte Buddy重写了JVM的默认lambda元工厂类,并将其替换为可以进行此类检测的自己的代码生成。