cor*_*zza 8 java junit class classloader
我必须从一些JAR动态加载具有相同名称的类,但是多次执行不同的实现.
我正在创建一个评估器后端,我必须动态加载类并测试它们.
测试是JUnit类,它们实例化应该测试的类,这是一个简单的例子:
package evaluator.tests;
import static org.junit.Assert.*;
import org.junit.*;
import evaluator.tested.*;
public class KTest {
private K tested;
@Before
public void setup() {
tested = new K();
}
@Test
public void returnsTrueTest() {
assertTrue(tested.returnsTrue());
}
}
Run Code Online (Sandbox Code Playgroud)
我的应用程序的其余部分需要从用户接收JAR文件,这些文件将包含K
上面正在测试的类的实现.然后,KTest
必须运行他们的 K
类,而不是应用程序中的类.
我知道如何动态加载一个类,但我不知道如何使用它进行测试,而不是我所做的那个.
我提出的解决方案之一是在一个全新的类中隔离测试,例如Evaluation
,在该类中创建一个新的类加载器,并使其加载所有引用的类.在创建类加载器之后,它将K
从JAR文件加载该类.
这意味着每次用户提交他的JAR时,Evaluation
都会实例化一个单独的,它会创建自己的类加载器并启动JUnit测试.当发生这种情况时,测试将使用用户的实现K
,而不是默认的实现.
这可能吗,怎么办呢?
我读到类加载器总是问他们的父是否已经加载了一个类.这意味着我必须以某种方式"刷新"我从JAR文件中动态加载的所有类Evaluation
,以便它们将被卸载然后再次加载到另一个中Evaluation
.
加载类K
,测试类K
,卸载类K
,重复不同K
.
我已经就这个主题发表了一篇博文,其中对问题进行了进一步的解释。
\n\n经过一番研究,我想我已经找到了一种方法来完全实现我想要的目标。我还没有实现这个系统(一旦实现就会编辑答案),所以我希望得到在这方面更有经验的人的一些反馈。
\n\n这就是我理解 URLClassLoaders(以及一般的类加载器)工作方式的方式:
\n\nURLClassLoader.loadClass()
如果它\xe2\x80\x99是当前类加载器(用于执行方法/类),则会自动调用。该调用首先被委托给其父类加载器,如果没有找到任何内容,它会使用自己的自定义从findClass()
它拥有的 URL 之一加载它。loadClass()
这里(和类加载逻辑)只是从常规的ClassLoader
.
此方法 ( ) 的默认行为loadClass()
是首先将搜索委托给父级,如果父级找不到该类,则仅调用其自己的findClass()
. findClass()
默认情况下(在 )中,此方法 ( )ClassLoader
未实现,您应该自己实现它,方法是从某处(例如文件或网络)获取类的字节码并调用defineClass()
它们。
一旦你调用defineClass()
了某个类,只有那时你才被注册为该类的类加载器。在所有其他情况下,类加载要么委托给您的父级(矛盾的是,您不是正在加载的类的类加载器),要么抛出ClassNotFoundException
. 您无法在运行时更改某些类的类加载器,它在加载后就已设置,并且是常量。
我的所有测试类将尝试getClass().getClassLoader().loadClass()
它们引用的所有类 - 包括我的自定义测试类(这是所有类的常规行为,而不仅仅是我的测试,需要明确)。只要它们\xe2\x80\x99使用标准类,以及我的应用程序中不是待测试类的其他类,就应该将此类加载方法进一步委托给应用程序类加载器。然而,一旦他们尝试加载要测试的类,他们就需要获取自己的、专门加载的自定义版本。
我的应用程序的用例是,用户提交带有某个类的 JAR,然后对该 JAR 中的类运行期望此类具有某些方法的测试(使用 JUnit),然后将结果发送回用户。
\n\n解决方法如下:
\n\nURLClassLoader
并重新设计类加载逻辑。\n\nClassNotFoundException
.ClassNotFoundException
(实际上会被父类抛出)。URLClassLoader
defineClass()
调用我的测试类,该类将此自定义设置URLClassLoader
为测试类的父级loadClass()
。首先,他们将搜索 URL - 因此,如果他们\xe2\x80\x99 引用要测试的类,它将从那里加载。如果它们引用某些其他应用程序类或系统类,则自定义类加载逻辑将仅委托此调用,并且将返回已加载的(可能)类。正如我\xe2\x80\x99ve所说 - 我还没有\xe2\x80\x99t实现这个,我真的很希望你\xe2\x80\x99d在评论中指出我的错误。
\n\n我从中收集这些信息的资源:
\n\n 归档时间: |
|
查看次数: |
2995 次 |
最近记录: |