我试图将所有日志记录框架重定向到Spring Boot应用程序中的Log4j2.它适用于Java Commons Logging,SLF4J和Log4j1.x.
不幸的是,Java Util Logging(JUL)重定向不起作用,因为在应用程序类路径尚未完全组装时,Plexus Launcher会使用java.util.logging.Logger.
Log4j2文档要求设置VM参数-Djava.util.logging.manager = org.apache.logging.log4j.jul.LogManager或调用System.setProperty(“ java.util.logging.manager”,“ org. apache.logging.log4j.jul.LogManager“)方法使重定向工作.它们都不起作用:
>我的应用程序代码中的System.setProperty()来不及了.一些启动代码已经对LogManager或Logger进行了一些调用,以便无法再安装Redirection-LogManager.
> VM参数也不起作用,因为在以下情况下,应用程序类路径在该时间点不可用:
对System.setProperty()的调用将被忽略,因为Java Util Logging框架已经初始化.使用VM参数时,会发生以下异常:
$mvn spring-boot:run -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
Could not load Logmanager "org.apache.logging.log4j.jul.LogManager"
java.lang.ClassNotFoundException: org.apache.logging.log4j.jul.LogManager
at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:50)
at org.codehaus.plexus.classworlds.realm.ClassRealm.unsynchronizedLoadClass(ClassRealm.java:271)
at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:247)
at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:239)
at java.util.logging.LogManager$1.run(LogManager.java:195)
at java.util.logging.LogManager$1.run(LogManager.java:181)
at java.security.AccessController.doPrivileged(Native Method)
at java.util.logging.LogManager.(LogManager.java:181)
at java.util.logging.Logger.demandLogger(Logger.java:448)
at java.util.logging.Logger.getLogger(Logger.java:502)
at com.google.inject.internal.util.Stopwatch.(Stopwatch.java:27)
at com.google.inject.internal.InternalInjectorCreator.(InternalInjectorCreator.java:61)
at com.google.inject.Guice.createInjector(Guice.java:96)
at com.google.inject.Guice.createInjector(Guice.java:73)
at com.google.inject.Guice.createInjector(Guice.java:62)
at org.codehaus.plexus.DefaultPlexusContainer.addPlexusInjector(DefaultPlexusContainer.java:481)
at org.codehaus.plexus.DefaultPlexusContainer.(DefaultPlexusContainer.java:206)
at org.apache.maven.cli.MavenCli.container(MavenCli.java:542)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:279)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:197)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
深入研究代码表明,初始化是由Guice库引起的,该库在内部使用JUL.在这种情况下,这只是对com.google.inject.internal.util.Stopwatch.< clinit>(Stopwatch.java:27)的调用.
所以问题是,有人对如何解决这个问题有想法吗?
更新2015-08-23:
从下面的建议添加配置属性< fork> true< / fork>.通过Spring boot Maven插件mvn spring-boot:run运行该应用程序.
不幸的是,当通过命令行java -Djava.util.logging.manager = org.apache.logging.log4j.jul.LogManager -jar myapp.jar运行应用程序时,它不起作用.在这种情况下,将发生以下异常:
Could not load Logmanager "org.apache.logging.log4j.jul.LogManager"
java.lang.ClassNotFoundException: org.apache.logging.log4j.jul.LogManager
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.util.logging.LogManager$1.run(LogManager.java:195)
at java.util.logging.LogManager$1.run(LogManager.java:181)
at java.security.AccessController.doPrivileged(Native Method)
at java.util.logging.LogManager.(LogManager.java:181)
at java.util.logging.Logger.demandLogger(Logger.java:448)
at java.util.logging.Logger.getLogger(Logger.java:502)
at org.springframework.boot.loader.Launcher.(Launcher.java:43)
at org.springframework.boot.loader.ExecutableArchiveLauncher.(ExecutableArchiveLauncher.java:48)
at org.springframework.boot.loader.ExecutableArchiveLauncher.(ExecutableArchiveLauncher.java:45)
at org.springframework.boot.loader.JarLauncher.(JarLauncher.java:30)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:45)
因此,不幸的是,Spring Boot Launcher也使用Java Util日志记录,从而阻止了Log4j2的JUL重定向.
我查看了org.springframework.boot.loader.Launcher类及其子类的源代码.该问题是由于在Launcher类中声明了静态logger变量引起的.该记录器似乎未由任何Launcher类使用,因此可以轻松将其删除.
问题是,是否可以完全消除对JUL的依赖关系以解决JUL重定向问题?也许通过将stderr用于启动器诊断而不是JUL?
解决方法:
您当前的方法意味着Maven和您的应用程序都将尝试使用自定义日志管理器. Maven尝试使用它会导致您看到的异常.
您可以在pom.xml中配置Spring Boot的Maven插件,为应用程序派生一个单独的JVM:
org.springframework.boot
spring-boot-maven-plugin
true
然后在应用程序的主方法中使用System.setProperty.在您的配置生效之前,分叉一个单独的JVM可以防止Maven自己的日志混乱.
标签:spring-boot,spring,java
来源: https://codeday.me/bug/20191119/2039197.html