我正在创建一个URLClassloader来加载一些jar。每个jar都从不同的类加载器中正确加载,每个jar包含一个带有方法run()的类。现在,这个run()的主体可以在其中创建一个匿名内部类。但是,因为我在try-with-resources块中创建了URLClassloader,它会自动关闭,并且在运行时尝试加载匿名内部类时会抛出NoClassDefFoundError,因为类加载器已经关闭。
现在我的问题是,这些情况的正常做法是什么?是否可以让类加载器保持打开状态,以便以后需要加载其他内容时,它可以吗?有没有办法重新打开一个封闭的类加载器?
如果我让类加载器保持打开状态,编译器会向我发出有关潜在资源泄漏的警告所以我感觉这就像流不会让它们无限期地打开。但是由于类加载器的性质,如果它不是加载匿名类的相同类加载器,则它不能在外层类中使用
这是创建类加载器的代码
public Player(File codePath) throws PlayerException {
try (URLClassLoader loader = new URLClassLoader(new URL[] { codePath.toURI().toURL() })) {
//load class from Jar where run() method creates anonymous class that comes in the jar too
} catch (ClassCastException | IOException | ClassNotFoundException | InstantiationException
| IllegalAccessException | IllegalArgumentException | InvocationTargetException
| SecurityException exc) {
throw new PlayerException("Error loading player's code", exc);
}
答案 0 :(得分:3)
类加载器的生命周期至少应该是加载它的类实例的生命周期。只要他们和他们的类不符合垃圾收集资格,他们的类加载器也不是。如果他们需要加载额外的代码或资源,您需要打开类加载器。
所以当你完成一个玩家时,就应该关闭这个类加载器了。
答案 1 :(得分:0)
您可以使用工厂模式(或类似的东西),而不是为每个玩家创建一个新的类加载器:
URLClassLoader loader = PlayerClassLoaderFactory.getInstance().getClassLoader(codePath.toURI())
工厂维护对类加载器的引用(因此类不是孤立的)。然后,如果需要关闭类加载器,您就可以“关闭”工厂。