如何在java中重新定义lambda匿名类
JDK8将lambda表达式转换为中的匿名类如何在java中重新定义lambda匿名类,java,lambda,java-8,javaagents,Java,Lambda,Java 8,Javaagents,JDK8将lambda表达式转换为中的匿名类 InnerClassLambdaMetafactory.spinInnerClass() { return UNSAFE.defineAnonymousClass(targetClass, classBytes, null); } 我正在编写一个javaagent,使用asm修改classBytes(添加一个方法)并将其传递给defineAnonymousClass,但该方法最终得到了这个匿名类的ClassNotFoundException
InnerClassLambdaMetafactory.spinInnerClass() {
return UNSAFE.defineAnonymousClass(targetClass, classBytes, null);
}
我正在编写一个javaagent,使用asm修改
classBytes
(添加一个方法)并将其传递给defineAnonymousClass
,但该方法最终得到了这个匿名类的ClassNotFoundException。有什么方法可以修改匿名类字节的内容吗?转换匿名加载的类很棘手。是否重新格式化表示此类类的已加载类?如果是这样,请注意Class::getName
不会返回类的实际二进制名称,而是添加一个随机散列,例如my.DefinedType/12345
,您需要在其中去除最新的数字
此外,您不能直接从另一个类引用此类类,但需要直接从反射API或理想情况下的方法句柄引用它们。您无法从类加载器中查找此类类,这就是它们被称为匿名类的原因
最后,在安装类文件转换器时,此类匿名类的加载不会在转换器中注册。处理此类类的最简单方法是修补负责创建lambda类型的lambda元工厂。例如,您可以使用以下工具轻松创建代理:
new AgentBuilder.Default()
.with(LambdaTransformationStrategy.ENABLED)
.type(someMatcher)
.transform(someTransformer)
.installOn(instrumentation);
在封面下调用此函数,Byte Buddy将重写JVM的默认lambda元工厂类,并在可能进行此类插装的情况下使用其自己的代码生成来替换它。其他类可以直接引用匿名类,如果它们也是匿名类并且具有修补的常量池(这是
defineAnonymousClass
的第三个参数)。在这种情况下,他们使用的名称也无关紧要。这是事实。但这不适用于描述lambda表达式的类。谢谢你的回答,我不是在尝试重新定义已加载的类,而是在创建匿名类之前修改其字节。仍然不知道它为什么不起作用。关于通过targetClass.getClassLoader.defineClass(modifyedAnonymousClassBytes)定义匿名类
?有任何副作用吗?@nzomkxia:当您试图在加载时更改类的字节码时,您必须在ClassFileTransformer
的实现中进行更改。在这种情况下,您应该既不调用defineClass
也不调用defineAnonymousClass
,只需返回修改后的字节码即可。将字节码传递给targetClass的defineClass
方法ClassLoader
很少起作用。首先,匿名类可以访问目标类的private
方法,这对于普通类是不允许的,其次,targetClass
可能是一个引导类,具有null
类装入器.