kos*_*ta5 3 java reflection classloader byte-buddy
我们有一个带有自定义类加载器的应用程序,我需要访问给定类的 classLoader 字段。但是,无法通过反射访问此字段:-(
JavaDoc forjava.lang.Class很清楚:
// This field is filtered from reflection access, i.e. getDeclaredField
// will throw NoSuchFieldException
Run Code Online (Sandbox Code Playgroud)
所以这就是我在调用时getDeclaredField("classLoader")
得到的结果 可以以某种方式获得(我看到 IntelliJ 调试以某种方式这样做;如何?)
也许是一些byteBuddy诡计?
回答您的问题:您仍然可以通过创建类的镜像来使用 Byte Buddy 进入该字段,该镜像将具有类似的类布局,以便您可以Unsafe通过首先创建隐藏类的镜像来访问和修改字段来自反射的字段:
Class<?> mirror = new ByteBuddy()
.with(TypeValidation.DISABLED)
.redefine(Class.class)
.name("mirror.Class")
.noNestMate()
.make()
.load(null)
.getLoaded();
Class<?> unsafeType = Class.forName("sun.misc.Unsafe");
Field theUnsafe = unsafeType.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Object unsafe = theUnsafe.get(null);
long offset = (Long) unsafeType
.getMethod("objectFieldOffset", Field.class)
.invoke(unsafe, mirror.getDeclaredField("classLoader"));
ClassLoader loader = (ClassLoader) unsafeType
.getMethod("getObject", Object.class, long.class)
.invoke(unsafe, Foo.class, offset - 4);
Run Code Online (Sandbox Code Playgroud)
镜像具有与原始类相似的字段布局,以便您可以根据需要保留该布局和访问字段。您可以以相同的方式使用putObject来覆盖字段值。
但是,我会推荐这种方法吗?绝对不。这也将在任何未来版本的 Java 中停止工作。如果您需要一些额外的时间来处理适当的解决方案,这可能是一种可行的方法,但从长远来看,您应该重构代码以使这种变通方法变得不必要。
| 归档时间: |
|
| 查看次数: |
780 次 |
| 最近记录: |