Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
更改Java类加载器的优先级_Java_Log4j_Classloader_Slf4j_Jca - Fatal编程技术网

更改Java类加载器的优先级

更改Java类加载器的优先级,java,log4j,classloader,slf4j,jca,Java,Log4j,Classloader,Slf4j,Jca,可能已经有人问过了,但如果是这样,我就找不到了 提问 在Java1.7/1.8中,除了实现自定义类加载器之外,是否有办法使应用程序类路径比扩展类路径具有更高的优先级(更早加载) 问题 我们有一个使用Apache的log4j库的多应用程序平台。我们还在[jre]/lib/ext中安装了一个自定义JCA安全提供程序,它也使用log4j。为此,必须将log4j与提供程序一起安装在ext目录中 平台上的一个应用程序(Apache的activemq)依赖于比提供商更旧的log4j/slf4j版本。而且,由

可能已经有人问过了,但如果是这样,我就找不到了

提问 在Java1.7/1.8中,除了实现自定义类加载器之外,是否有办法使应用程序类路径比扩展类路径具有更高的优先级(更早加载)

问题 我们有一个使用Apache的log4j库的多应用程序平台。我们还在[jre]/lib/ext中安装了一个自定义JCA安全提供程序,它也使用log4j。为此,必须将log4j与提供程序一起安装在ext目录中

平台上的一个应用程序(Apache的activemq)依赖于比提供商更旧的log4j/slf4j版本。而且,由于提供程序的log4j jar位于[jre]/lib/ext中,它们会覆盖activemq,从而导致出现NoSuchMethodError:

java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log(Lorg/slf4j/Marker;Ljava/lang/String;ILjava/lang/String;Ljava/lang/Throwable;)V
那么,有没有办法让应用程序类路径中的JAR取代扩展目录

繁殖 您可以通过将这些JAR安装到[jre]/lib/ext中来重现此问题:

  • log4j-1.2.17.jar
  • slf4j-api-1.7.2.jar
  • slf4j-log4j12-1.7.2.jar
通过在应用程序类路径中安装这些JAR:

  • log4j-1.2.14.jar
  • slf4j-api-1.5.11.jar
  • slf4j-log4j12-1.5.11.jar
通过运行以下代码:

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import org.slf4j.LoggerFactory;
import org.slf4j.spi.LocationAwareLogger;

public class LogApp {

    public final static LocationAwareLogger logger =
            (LocationAwareLogger) LoggerFactory.getLogger(LogApp.class);

    public static void main(String[] args) throws NoSuchAlgorithmException {
        // Make sure custom security provider has been initialized.
        SecureRandom rand = SecureRandom.getInstanceStrong();
        rand.doubles();

        //ClassLoader cl = ClassLoader.getSystemClassLoader();

        LogApp.logger.error("error: {}: {}", "string", new Exception());
        LogApp.logger.log(null, LogApp.class.getCanonicalName(),
                logger.ERROR_INT, "some message", new Exception());
    }

}
这将生成此错误:

Exception in thread "main" java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log(Lorg/slf4j/Marker;Ljava/lang/String;ILjava/lang/String;Ljava/lang/Throwable;)V
    at LogApp.main(LogApp.java:23)
答复 使用以下参数运行Java:

-Xbootclasspath/p:[path_to_app_libs]/log4j-1.2.14.jar:[path_to_app_libs]/slf4j-api-1.5.11.jar:[path_to_app_libs]/slf4j-log4j12-1.5.11.jar

如果您可以控制java的运行方式,那么可以使用-Xbootclasspath/a:path/to/your.jar强制在扩展之前加载特定的jar

在lib/ext中升级log4j可能是更容易的解决方案。希望lib/ext中需要log4j的东西能够在新版本中生存,否则,在任何情况下都会有问题,因为bootclasspath将优先并强制lib/ext代码使用新版本


在任何情况下,使用特定版本的log4j库都是不好的做法。除最终应用程序外,可能使用slf4j而无需特定绑定,也可能在7月使用。

谢谢!“在lib/ext中升级log4j可能是更容易的解决方案。”这些jar比activemqjar更新。您可能会说升级是导致此问题的原因:)。“在任何情况下,让库具有特定版本的log4j都是不好的做法。”同意。但它是Apache的activemq的外部依赖项,而不是我们的应用程序。不幸的是,这似乎是JRockit特有的:(实际上,标准JVM确实接受它,但我还没有让它工作。不仅是JRockit,它在Sun/Oracle和IBM JDK中已经存在了很长时间。我终于让它工作了。我必须将-Xbootclasspath/p指向所有三个JAR,而不是它们的目录。谢谢!