我正在尝试为代理编写UnitTest,以拦截来自java.io(例如FileInputStream)的类的调用。

我遵循了here给出的提示,并查看了ByteBuddys own UnitTests。

private ClassLoader classLoader;

@Before
@AgentAttachmentRule.Enforce
public void setUp() throws Exception
{
    classLoader = new ByteArrayClassLoader.ChildFirst(getClass().getClassLoader(),
                                           ClassFileExtraction.of(FileInputStream.class),
                                           DEFAULT_PROTECTION_DOMAIN,
                                           AccessController.getContext(),
                                           ByteArrayClassLoader.PersistenceHandler.MANIFEST,
                                           PackageDefinitionStrategy.NoOp.INSTANCE);
}

@Test
public void testAgentForFileInputStream() throws Exception
{
    MyAgent.premain("");
    Class<?> type = classLoader.loadClass(FileInputStream.class.getName());
    type.getDeclaredMethod("open").invoke("test");
}


对于非java。*类的类似测试也可以,但是在这里我收到:

java.lang.SecurityException: Prohibited package name: java.io

at java.lang.ClassLoader.preDefineClass(ClassLoader.java:659)
at java.lang.ClassLoader.defineClass(ClassLoader.java:758)
at net.bytebuddy.dynamic.loading.ByteArrayClassLoader.findClass(ByteArrayClassLoader.java:197)
at net.bytebuddy.dynamic.loading.ByteArrayClassLoader$ChildFirst.loadClass(ByteArrayClassLoader.java:554)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)


我尝试将SecurityManager设置为null,但没有成功:

System.setSecurityManager(null);


如果我没记错的话,应该可以拦截此类。这可能是由于使用了自定义的ClassLoader。但是我不知道需要改变什么...

最佳答案

从引导程序类加载器无法从任何类加载器加载任何带有java.前缀的类。此限制不是由SecurityManager强制实施的,而是硬编码到ClassLoader实现中的。

测试这些类的唯一方法是:


在测试过程中调整名称,以允许在另一个类加载器中加载。
将类加载到引导类加载器中(使用ByteBuddyAgentClassInjector.ForInstrumentation)。您仍应将名称随机化以保证测试的可重复性。


在您的情况下,只有选项2可行。因为我不知道您的代理在做什么,所以我只能假设您尝试在任何情况下都需要使用引导加载程序注入的情况下操纵FileInputStream类,因为此类的复制不适用于该类的本机方法适配器。

09-26 22:42
查看更多