log4j2 与 Java 11 兼容吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/53049346/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is log4j2 compatible with Java 11?
提问by Dmitriy Dumanskiy
I tried to run my project on the latest Java 11. Everything works, except the specific file logger. Logging works fine on previous Java versions - 10, 9, 8, but not on Java 11.
我尝试在最新的 Java 11 上运行我的项目。除了特定的文件记录器之外,一切正常。日志记录适用于以前的 Java 版本 - 10、9、8,但不适用于 Java 11。
During server run I see only 1 warning:
在服务器运行期间,我只看到 1 个警告:
WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.
警告:不支持 sun.reflect.Reflection.getCallerClass。这会影响性能。
Here is my configuration:
这是我的配置:
<Configuration>
<Appenders>
<RollingFile name="postgresDBLog" fileName="${sys:logs.folder}/postgres.log"
filePattern="${sys:logs.folder}/archive/postgres.log.%d{yyyy-MM-dd}">
<PatternLayout>
<pattern>%d{HH:mm:ss.SSS} - %msg%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy/>
</Policies>
</RollingFile>
<RollingFile name="workersLog" fileName="${sys:logs.folder}/worker.log"
filePattern="${sys:logs.folder}/archive/worker.log.%d{yyyy-MM-dd}">
<PatternLayout>
<pattern>%d{HH:mm:ss.SSS} - %msg%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy/>
</Policies>
</RollingFile>
<RollingFile name="statsLog" fileName="${sys:logs.folder}/stats.log"
filePattern="${sys:logs.folder}/archive/stats.log.%d{yyyy-MM-dd}">
<PatternLayout>
<pattern>%msg%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy/>
</Policies>
</RollingFile>
<RollingFile name="userLog" fileName="${sys:logs.folder}/blynk.log"
filePattern="${sys:logs.folder}/archive/blynk.log.%d{yyyy-MM-dd}">
<PatternLayout>
<pattern>%d{HH:mm:ss.SSS} %-5level- %msg%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="cc.blynk.server.workers" level="debug" additivity="false">
<appender-ref ref="workersLog"/>
</Logger>
<Logger name="cc.blynk.server.workers.StatsWorker" level="debug" additivity="false">
<appender-ref ref="statsLog"/>
</Logger>
<Logger name="cc.blynk.server.db" level="debug" additivity="false">
<appender-ref ref="postgresDBLog"/>
</Logger>
<Logger name="com.zaxxer.hikari" level="OFF" additivity="false">
</Logger>
<Logger name="org.asynchttpclient.netty.channel" level="OFF" additivity="false" />
<!-- turn off netty errors in debug mode for native library loading
https://github.com/blynkkk/blynk-server/issues/751 -->
<Logger name="io.netty" level="INFO" additivity="false" />
<Root>
<AppenderRef ref="userLog"/>
</Root>
</Loggers>
</Configuration>
All loggers, except userLog
works fine. However, userLog
is empty.
所有记录器,除了userLog
工作正常。然而,userLog
是空的。
log4j2 version 2.11.1
Ubuntu 16.04.5 LTS
java version "11.0.1" 2018-10-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.1+13-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.1+13-LTS, mixed mode)
Update:
更新:
Adding level="info"
to the root level fixes the issue.
添加level="info"
到根级别可解决此问题。
<Root level="info">
<AppenderRef ref="userLog"/>
</Root>
However, in my project I was using a code that was setting a log level based on properties file. Here is a code:
但是,在我的项目中,我使用了基于属性文件设置日志级别的代码。这是一个代码:
private static void changeLogLevel(String level) {
Level newLevel = Level.valueOf(level);
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration conf = ctx.getConfiguration();
conf.getLoggerConfig(LogManager.ROOT_LOGGER_NAME).setLevel(newLevel);
ctx.updateLoggers(conf);
}
Seems like this part is no longer work with Java 11.
似乎这部分不再适用于 Java 11。
采纳答案by dadoonet
If someone is using Maven and is having the same issue while assembling a flat jar, here is what I did to fix the same issue:
如果有人正在使用 Maven 并且在组装扁平罐时遇到同样的问题,这是我为解决同样问题所做的工作:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>foo.bar.Generate</mainClass>
<manifestEntries>
<Multi-Release>true</Multi-Release>
</manifestEntries>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
The important part is <Multi-Release>true</Multi-Release>
.
重要的部分是<Multi-Release>true</Multi-Release>
。
Note that the Java code I'm using now to change loggers level is:
请注意,我现在用来更改记录器级别的 Java 代码是:
Configurator.setAllLevels("foo.bar", Level.DEBUG);
回答by rgoers
If you are getting this message then your application is not setup to use multi-release jars. Log4j supports Java 9+ by using Stackwalker in a version of StackLocator that is located in META-INF/versions/9. Depending on how your application works, you may need to have Multi-Release set to true in the jar manifest. This is true for Spring Boot jars. Without multi-release support you will use the pre-Java 9 version of StackLocator which tries to use Reflection.getCallerClass(). That class was removed in Java 9. Log4j will fall back to a slower way to calculate stack locations but it will still work. Hence the warning.
如果您收到此消息,则说明您的应用程序未设置为使用多版本 jar。Log4j 通过在位于 META-INF/versions/9 的 StackLocator 版本中使用 Stackwalker 来支持 Java 9+。根据您的应用程序的工作方式,您可能需要在 jar 清单中将 Multi-Release 设置为 true。这适用于 Spring Boot jar。如果没有多版本支持,您将使用 Java 9 之前的 StackLocator 版本,它尝试使用 Reflection.getCallerClass()。该类在 Java 9 中被删除。Log4j 将回退到计算堆栈位置的较慢方法,但它仍然可以工作。因此警告。
回答by Damien
Seems like this part is no longer work with Java 11.
似乎这部分不再适用于 Java 11。
I ran into the same problem with programmatically updating LogLevel settings using the LoggerContext after upgrading to JDK 11 from JDK 8. If the LogManager.getContext(boolean)
can't find the LoggerContext it will create and return a new instance — changing that new object will have no effect. Specifying the classloader of Log4j's LogManager class fixed the issue in our case:
从 JDK 8 升级到 JDK 11 后,我在使用 LoggerContext 以编程方式更新 LogLevel 设置时遇到了同样的问题。如果LogManager.getContext(boolean)
找不到 LoggerContext,它将创建并返回一个新实例——更改该新对象将不起作用。指定 Log4j 的 LogManager 类的类加载器修复了我们案例中的问题:
LoggerContext ctx = (LoggerContext) LogManager.getContext(LogManager.class.getClassLoader(), false);
回答by Svante Schubert
Log4J2 is of course compatible it uses the JDK Multi-Release featureor in more detail.
Log4J2 当然是兼容的,它使用JDK Multi-Release 功能或更详细地说明。
BUT...
但...
1) First, when you are using - like me - the slf4j interface, you need to use a different Maven artefact, see http://logging.apache.org/log4j/2.x/log4j-slf4j-impl/index.html
1)首先,当您像我一样使用 slf4j 接口时,您需要使用不同的 Maven 人工制品,请参阅http://logging.apache.org/log4j/2.x/log4j-slf4j-impl/index。 html
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j18-impl</artifactId>
<version>2.12.1</version>
</dependency>
which adds all dependencies as 'mvn dependency:tree' reveals:
它将所有依赖项添加为“mvn dependency:tree”显示:
\- org.apache.logging.log4j:log4j-slf4j18-impl:jar:2.12.1:compile
[INFO] +- org.slf4j:slf4j-api:jar:1.8.0-alpha2:compile
[INFO] +- org.apache.logging.log4j:log4j-api:jar:2.12.1:compile
[INFO] \- org.apache.logging.log4j:log4j-core:jar:2.12.1:runtime
2) And second, when you are creating - like me - one single JAR, which includes all dependencies, you need to add the Multi-Release manifest entry as well, see https://issues.apache.org/jira/browse/LOG4J2-2537or in my project's pom.xmland search for
2) 其次,当您像我一样创建一个包含所有依赖项的 JAR 时,您还需要添加多版本清单条目,请参阅https://issues.apache.org/jira/browse/ LOG4J2-2537或在我项目的pom.xml 中搜索
<Multi-Release>true</Multi-Release>
回答by Lorinczy Zsigmond
This message comes from org/apache/logging/log4j/util/StackLocator.<classconstructor>
which is part of log4j2-api.jar
(or log4j-api-2.x.y.jar
etc).
此消息来自org/apache/logging/log4j/util/StackLocator.<classconstructor>
哪个是的一部分log4j2-api.jar
(或log4j-api-2.x.y.jar
等)。
You get this message because some smart guys decided sun.reflect.Reflection.getCallerClass
has to be removed from JRE (guess they pulled a page from Herostratus's book or something). This actually happened in Openjdk11.
您收到此消息是因为一些聪明人决定 sun.reflect.Reflection.getCallerClass
必须从 JRE 中删除(猜想他们从 Herostratus 的书或其他东西中提取了一页)。这实际上发生在 Openjdk11 中。
Mind you, you shouldn't get this message if you have a not-too-old version of log4j2-api.jar
, as it is a multi-release-jarmeaning it contains another implementation of this class for Java9+ (META-INF/versions/9/org/apache/logging/log4j/util/StackLocator.class
) which doesn't give this message.
请注意,如果您有一个不太旧的版本log4j2-api.jar
,则不应收到此消息,因为它是一个多版本 jar,这意味着它包含 Java9+ ( META-INF/versions/9/org/apache/logging/log4j/util/StackLocator.class
)的此类的另一个实现,它没有给出此消息.
But, if you use some Helping Product(TM), such as Spring Boot, that has its own classloader, it might not be multi-relase-jar compatible, so it loads the Java8 compatible StackLocator.class
instead of the Java9+ compatible, and you still get this message.
但是,如果你使用一些 Helping Product(TM),比如 Spring Boot,它有自己的类加载器,它可能不兼容 multi-relase-jar,所以它加载 Java8 兼容StackLocator.class
而不是 Java9+ 兼容,你仍然得到这条信息。