【发布时间】:2017-10-08 23:43:34
【问题描述】:
我正在尝试从我的应用程序代码中的FilePermission 有效地访问cpath 字段。请注意,这应该可以通过安全管理器来完成,所以如果可能的话,我不想求助于调用 setAccessible。
我已经在通过 AgentBuilder 使用 Byte Buddy 支持的代理。以下是 AgentBuilder 的作用:
public static void premain(String arg, Instrumentation inst) {
install(arg, inst);
}
public static void agentmain(String arg, Instrumentation inst) {
install(arg, inst);
}
private static void install(String arg, Instrumentation inst) {
Transformer filePermissionTransformer = (builder, typeDescription, classLoader, module) ->
builder.field(named("cpath")).transform(ForField.withModifiers(Visibility.PUBLIC));
new AgentBuilder.Default()
.with(new ByteBuddy().with(Implementation.Context.Disabled.Factory.INSTANCE))
.with(Listener.StreamWriting.toSystemOut())
.with(InitializationStrategy.NoOp.INSTANCE)
.with(RedefinitionStrategy.REDEFINITION)
.with(TypeStrategy.Default.REDEFINE)
.ignore(none())
.type(named("java.io.FilePermission"))
.transform(filePermissionTransformer)
.installOn(inst);
}
我可以通过 sysout 监听器看到它确实正在被转换:
[Byte Buddy] DISCOVERY java.io.FilePermission [null, null, loaded=true]
[Byte Buddy] TRANSFORM java.io.FilePermission [null, null, loaded=true]
[Byte Buddy] COMPLETE java.io.FilePermission [null, null, loaded=true]
然后我尝试在应用程序中获取该字段:
if (perm instanceof FilePermission) {
Field cpathField = perm.getClass().getDeclaredField("cpath");
String cpath = (String) cpathField.get(perm);
}
但这会导致 IllegalAccessException,原因告诉我它仍然是“私有瞬态”。
只是为了好玩,我尝试了 .annotateField 而不是 .transform 带有弃用注释。这确实有效,并且在运行时我可以从声明的字段中检索注释。所以这至少证明了字段转换的路径是有效的……只是由于某种原因不是这个特定的转换。
仅作为背景,不,这不是我使用 Byte Buddy 的唯一原因...我还使用它来重新定义其他一些东西。我可以自己参考 OpenJDK 代码计算cpath,但我希望它尽可能高效......而且由于 FilePermission 已经在内部完成工作,我宁愿获取价值也不愿做两次工作。由于我已经在其他事情上使用仪器,这似乎是一个更优雅的解决方案。
干杯!
【问题讨论】:
标签: java bytecode instrumentation javaagents byte-buddy