gpt4 book ai didi

java - 使用 ASM 或 Javassist 提高字段获取和设置性能

转载 作者:太空狗 更新时间:2023-10-29 22:56:27 25 4
gpt4 key购买 nike

我想避免在我正在开发的开源项目中进行反射(reflection)。在这里,我有如下类。

public class PurchaseOrder {

@Property
private Customer customer;

@Property
private String name;
}

我扫描 @Property 注释以确定我可以反射性地从 PurchaseOrder 设置和获取什么。有许多这样的类都使用 java.lang.reflect.Field.get()java.lang.reflect.Field.set()

理想情况下,我想为每个属性生成一个调用程序,如下所示。

public interface PropertyAccessor<S, V> {
public void set(S source, V value);
public V get(S source);
}

现在,当我扫描类时,我可以像这样创建 PurchaseOrder 的静态内部类。

static class customer_Field implements PropertyAccessor<PurchaseOrder, Customer> {
public void set(PurchaseOrder order, Customer customer) {
order.customer = customer;
}
public Customer get(PurchaseOrder order) {
return order.customer;
}
}

有了这些,我就完全避免了反射(reflection)的代价。我现在可以使用 native 性能设置和获取实例。谁能告诉我该怎么做。一个代码示例会很棒。我在网上搜索了一个很好的例子,但找不到这样的东西。 ASM 和 Javasist 示例也很差。

这里的关键是我有一个可以传递的接口(interface)。所以我可以有多种实现,也许一种是默认使用 Java 反射,一种是使用 ASM,另一种是使用 Javassist?

如有任何帮助,我们将不胜感激。

最佳答案

ASM

使用ASMifierClassVisitor,您可以准确地看到您需要编写哪些代码来生成内部类:

ASMifierClassVisitor.main(new String[] { PurchaseOrder.customer_Field.class
.getName() });

剩下的只是确定您需要在生成器代码中参数化哪些位。 PurchaseOrder$customer_Field 的示例输出将成为文件 inject/PurchaseOrder$customer_Field.class:

public static byte[] dump () throws Exception {

ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;

cw.visit(V1_6, ACC_SUPER, "inject/PurchaseOrder$customer_Field",
"Ljava/lang/Object;"+
"Linject/PropertyAccessor<Linject/PurchaseOrder;Linject/Customer;>;",
"java/lang/Object",
new String[] { "inject/PropertyAccessor" });
//etc

(我使用“inject”作为包。)

您还必须使用 ASM 的访问者类创建合成访问器:

{
mv = cw.visitMethod(ACC_STATIC + ACC_SYNTHETIC, "access$0",
"(Linject/PurchaseOrder;Linject/Customer;)V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitFieldInsn(PUTFIELD, "inject/PurchaseOrder",
"customer", "Linject/Customer;");
mv.visitInsn(RETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_STATIC + ACC_SYNTHETIC, "access$1",
"(Linject/PurchaseOrder;)Linject/Customer;", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, "inject/PurchaseOrder", "
customer", "Linject/Customer;");
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}

参见 this project有关如何注入(inject)方法的示例。


With these I totally avoid the cost of reflection.

因为这一切都将在运行时完成:

  • 此解析和代码生成需要前期成本
  • 您需要以某种方式发现和反省这些生成的类型

关于java - 使用 ASM 或 Javassist 提高字段获取和设置性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3022741/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com