我正在尝试从应用程序代码中的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 ......我也用它来重新定义其他一些东西。我可以自己计算cpath
引用OpenJDK代码,但我希望它尽可能高效...而且由于FilePermission已经在内部完成工作,我宁愿抓住价值而不是工作两次。由于我已经在其他方面使用仪器,这似乎是一个更优雅的解决方案。
干杯!
答案 0 :(得分:1)
如果运行将属性-Dnet.bytebuddy.dump
设置为某个文件夹的程序,Byte Buddy将提取生成的类文件并将其写入指定的文件夹。如果您使用 javap 调查FilePermission
创建的文件,则会获得:
Compiled from "FilePermission.java"
public final class java.io.FilePermission extends java.security.Permission implements java.io.Serializable {
public transient java.lang.String cpath;
public java.io.FilePermission(java.lang.String, java.lang.String);
java.io.FilePermission(java.lang.String, int);
public boolean implies(java.security.Permission);
boolean impliesIgnoreMask(java.io.FilePermission);
public boolean equals(java.lang.Object);
public int hashCode();
int getMask();
public java.lang.String getActions();
public java.security.PermissionCollection newPermissionCollection();
static java.lang.String access$000(java.io.FilePermission);
}
如您所见,cpath
字段已公开,但JVM似乎并不关心这一点。如果您定义一个具有相同cpath
字段的类并运行上面的转换,这将有效。
我只能怀疑JVM在某个地方硬编码这个属性。你可以在JVM邮件列表上询问为什么会出现这种情况,我只能猜测。