我需要一种方法来访问反射性质的字段,而不会受到标准反射的性能影响。我已经找到了如何通过LambdaMetaFactory使用特权查找句柄使用方法/构造函数来实现这一点,然而,我似乎不知道如何获得字段访问权限。
我想我可以通过javaassist之类的东西生成一个内部类,理论上它应该可以访问该字段,但没有成功,抛出了一个IllegalAccessError。
如果我可以重新定义类,那么任务将是琐碎的,因为我可以生成getter/setter方法。然而,对于我正在进行的项目,我无法使用代理,因为它需要在运行时加载,并且我必须从工具中动态导入附加api。
有人能给我指引正确的方向吗?我研究了LambdaMetaFactory是如何生成方法接口的,并试图将其与字段进行镜像,但没有成功。字段和方法是否存在内部差异,导致在不重新定义的情况下无法完成此任务?
在OpendJDK(以及在其上构建的JDK(的情况下,LambdaMetaFactory
生成一个非常普通的类文件(只访问另一个类的private
成员(,并在sun.misc.Unsafe
中使用一种特殊的方法来创建一个匿名类。
创建一个访问字段的类似类文件是直接的,并用它创建一个匿名类是可行的,正如下面的quick&脏程序:
public class Generator {
public static void main(String[] args) throws Throwable {
ToIntFunction<Thread> ft=generateIntFieldAccessor(Thread.class, "threadStatus");
System.out.println(ft.applyAsInt(Thread.currentThread()));
}
private static <X> ToIntFunction<X> generateIntFieldAccessor(
Class<? super X> c, String name) throws Throwable {
byte[] code = Generator.generateIntReaderCode(c.getDeclaredField(name));
Class<?> unsafe = Class.forName("sun.misc.Unsafe");
Field u = unsafe.getDeclaredField("theUnsafe");
u.setAccessible(true);
Object theUnsafe = u.get(null);
Class<ToIntFunction<X>> gen = (Class<ToIntFunction<X>>)
MethodHandles.publicLookup().bind(theUnsafe, "defineAnonymousClass",
MethodType.methodType(
Class.class, Class.class, byte[].class, Object[].class))
.invokeExact(c, code, (Object[])null);
return gen.getConstructor().newInstance();
}
private static final String HEAD = "Êþº¾ 004 247 217 t7 n7 22"
+ "n 2 6f 13 ft 4 bf 23 201 20java/lang/Object1 40"
+ "java/util/function/ToIntFunction1 6<init>1 3()V1 4Code1 n"
+ "applyAsInt1 25(Ljava/lang/Object;)I1 1I";
private static final String TAIL = "