我正在尝试使用Class.forName在运行时从文件系统上的.jar文件动态加载类。我尝试加载的类在另一个.jar文件中实现了一个接口,因此我使用自己的URLClassLoader来引用这两个.jars。
该代码在未在Web应用程序上下文中被调用时有效(我已通过将方法复制并粘贴到单独的程序中并从main调用该方法进行了测试)。但是,当我运行/调试Web应用程序(我正在使用NetBeans)时,代码将失败。当我尝试将实例转换为jar_file_dependencies.jar中指定的接口时,newInstance方法将引发ClassCastException。
如果有帮助,请参见以下相关代码:
File gameJar = new File("C:\\file_path\\jar_file.jar");
File gameDependenciesJar = new File("C:\\file_path\\jar_file_dependencies.jar");
URLClassLoader cl = new URLClassLoader(new URL[]
{
gameJar.toURI().toURL(),
gameDependenciesJar.toURI().toURL()
});
Class clazz = Class.forName("MyClass", true, cl);
IMyClass myClass = (IMyClass)clazz.newInstance();
System.out.println(game);
} catch (Exception e)
{
System.out.println(e.getMessage());
}
关于为什么此代码在一个程序中而不在另一个程序中工作的任何建议将不胜感激。
非常感谢,
担
最佳答案
简短的答案,而无需涉及太多毛茸茸的细节:gameJar和gameDependenciesJar中的一个或两个都可能包含IMyClass类/接口的定义。使用子类加载器时的经验法则是,子类加载器不应包含任何“共享”类,它们只能存在于父类加载器中。
部分说明:Web应用程序类加载器通常具有与常规类加载器不同的委派策略。通常,他们比父母更喜欢孩子的课。普通的类加载器通常更喜欢父类而不是子类。在您的Web应用程序中,最终将得到2个IMyClass类的单独定义(父类加载器中一个def,子类中一个def)。在您的普通应用程序中,子类加载器中的IMyClass定义将被忽略,因此只有一个定义(在父类加载器中)被加载,并且一切都很顺利。