ByteBuddy:如何使用java中的类进行测试。*

时间:2016-05-23 19:32:53

标签: java junit classloader code-generation byte-buddy

我试图为拦截来自java.io的类调用的代理编写UnitTest(例如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。但是,我不知道需要改变什么......

1 个答案:

答案 0 :(得分:2)

不能从任何类加载器加载任何具有java.前缀的类,而是加载引导类加载器。 SecurityManager并未强制执行此限制,但已对ClassLoader实施进行硬编码。

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

  1. 在测试过程中调整名称以允许加载另一个类加载器。
  2. 将类加载到引导类加载器中(使用ByteBuddyAgentClassInjector.ForInstrumentation)。您仍应随机化名称以保证测试的可重复性。
  3. 在您的情况下,只有选项2似乎可行。由于我不知道你的代理正在做什么,我只能假设你试图操纵FileInputStream类,你需要在任何情况下使用bootstrap loader注入,因为这个类的复制不能用于类的本机方法适配器。