在Websphere上的Groovy中加载外部jar

在Websphere上的Groovy中加载外部jar,groovy,websphere,classloader,Groovy,Websphere,Classloader,我有一个部署在WebSphere8.5上的应用程序,类加载配置为“parentlast”。在应用程序中,我们使用GroovyScriptEngine运行groovy脚本文件 在这个groovy脚本文件中,我们使用: Thread.currentThread().getContextClassLoader().addURL( new URL("file:/test/ojdbc6.jar")) 加载外部jar文件。但它会导致错误: groovy.lang.MissingMethodExceptio

我有一个部署在WebSphere8.5上的应用程序,类加载配置为“parentlast”。在应用程序中,我们使用
GroovyScriptEngine
运行groovy脚本文件

在这个groovy脚本文件中,我们使用:

Thread.currentThread().getContextClassLoader().addURL( new URL("file:/test/ojdbc6.jar"))
加载外部jar文件。但它会导致错误:

groovy.lang.MissingMethodException: No signature of method: com.ibm.ws.classloader.CompoundClassLoader.addURL() is applicable for argument types: (java.net.URL) values: file:/test/ojdbc6.jar
我需要提到的两件事是:

  • 同样的应用程序和groovy在tomcat上工作得很好
  • 如果我将groovy更改为
    ClassLoader.systemClassLoader.addURL(新URL(“file:/test/ojdbc6.jar”)
    ,那么它在Websphere和tomcat上都可以正常工作
  • 我的问题
  • 此错误是否与Websphere上的“父上次”设置有关?为什么?
  • 为什么系统类加载器工作正常
    您必须检查javadoc,
    java.lang.ClassLoader
    ,它没有实现
    addURL()
    方法,而是由
    java.net.URLClassLoader
    实现的。
    CompoundClassLoader
    没有扩展它。因此,为了安全起见,您应该始终使用
    instanceof
    进行检查。如果没有,您可以尝试使用方法
    getParent()
    getSystemClassLoader()
    在堆栈的更高位置找到正确的类加载器

    问:这个错误与Websphere中的“父上次”设置有关吗?为什么?

    不完全是。然而,它与WebSphere中类装入器的模块化有关。在默认设置中,每个模块由单独的类加载器加载,并且模块类加载器没有扩展
    URLClassLoader
    。如果您要为服务器将服务器类加载器策略切换为Single,那么它将为所有应用程序使用Single classloader,但是它仍然是一个层次结构,因此它不会解决您的问题。有关详细信息,请查看此链接

    引用文章 当应用程序类加载器策略设置为Single时,则 单个应用程序类加载器加载所有EJB模块、依赖项和JAR 系统中的文件和共享库。什么时候申请 类加载器策略设置为多个,然后每个应用程序接收 它自己的类加载器,用于加载EJB模块, 依赖项JAR文件以及该应用程序的共享库

    但是对于你的问题,也许你应该考虑添加<代码> OJDBC6. jar <代码>作为一个?那么您就不需要嵌入代码来将其加载到应用程序中了

    下面是查看classloader层次结构的示例代码:

    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    do {
        System.out.println(classLoader.getClass().getName());
        System.out.println("Is URLClassLoader: " + (classLoader instanceof URLClassLoader));
        classLoader = classLoader.getParent();
    } while(classLoader != null);
    
    ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
    System.out.println("System: " + systemClassLoader.getClass().getName());
    System.out.println("Is URL: " + (systemClassLoader instanceof URLClassLoader));
    
    和输出:

    SystemOut     O com.ibm.ws.classloader.CompoundClassLoader
    SystemOut     O Is URLClassLoader: false
    SystemOut     O com.ibm.ws.classloader.CompoundClassLoader
    SystemOut     O Is URLClassLoader: false
    SystemOut     O com.ibm.ws.classloader.ExtJarClassLoader
    SystemOut     O Is URLClassLoader: false
    SystemOut     O com.ibm.ws.classloader.ProtectionClassLoader
    SystemOut     O Is URLClassLoader: false
    SystemOut     O com.ibm.ws.bootstrap.ExtClassLoader
    SystemOut     O Is URLClassLoader: true
    SystemOut     O org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader
    SystemOut     O Is URLClassLoader: false
    SystemOut     O sun.misc.Launcher$AppClassLoader
    SystemOut     O Is URLClassLoader: true
    SystemOut     O sun.misc.Launcher$ExtClassLoader
    SystemOut     O Is URLClassLoader: true
    SystemOut     O System: sun.misc.Launcher$AppClassLoader
    SystemOut     O Is URLClassLoader: true
    

    我转到websphere管理控制台>>服务器->服务器类型->websphere应用程序服务器->服务器1->类加载器策略,将其更改为Single,但没有帮助。@morven我的错误-即使是Single类加载器策略也在使用层次结构。检查我的更新。我不是groovy专家,但如果您想通过数据源(如果groovy提供)或共享库加载驱动程序,则不必在应用程序中硬编码加载JAR。非常感谢您的解释。我可以只使用ClassLoader.systemClassLoader.addURL(),它确实可以像我前面提到的那样工作,但由于我不熟悉它,所以不确定是否有任何副作用。@即使正在加载的库是自包含的,并且不需要任何其他依赖项,您也可以。但它将无法从应用程序中查找类,因为它们将由应用程序(子)类加载器加载。关于这些加载的库的详细信息太少,所以您需要进行测试。