web-dev-qa-db-fra.com

Log4j2 est-il compatible avec Java 11?

J'ai essayé d'exécuter mon projet sur la dernière version de Java 11. Tout fonctionne, sauf l'enregistreur de fichiers spécifique. La journalisation fonctionne correctement sur les versions précédentes de Java - 10, 9, 8, mais pas sur Java 11.

Pendant l'exécution du serveur, je ne vois qu'un seul avertissement:

AVERTISSEMENT: Sun.reflect.Reflection.getCallerClass n'est pas pris en charge. Ce aura un impact sur les performances.

Voici ma 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>

Tous les enregistreurs, à l'exception de userLog, fonctionnent bien. Cependant, userLog est vide.

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)

Mettre à jour:

L'ajout de level="info" au niveau racine corrige le problème.

    <Root level="info">
        <AppenderRef ref="userLog"/>
    </Root>

Cependant, dans mon projet, j'utilisais un code qui définissait un niveau de journalisation basé sur un fichier de propriétés. Voici un 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);
}

On dirait que cette partie ne fonctionne plus avec Java 11.

9
Dmitriy Dumanskiy

Si quelqu'un utilise Maven et rencontre le même problème lors de l'assemblage d'un pot plat, voici ce que j'ai fait pour résoudre le même problème:

<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>

La partie importante est <Multi-Release>true</Multi-Release>.

Notez que le code Java que j'utilise maintenant pour changer le niveau des enregistreurs est le suivant:

Configurator.setAllLevels("foo.bar", Level.DEBUG);
1
dadoonet

Si vous recevez ce message, votre application n'est pas configurée pour utiliser des fichiers jar à libérations multiples. Log4j prend en charge Java 9+ en utilisant Stackwalker dans une version de StackLocator située dans META-INF/versions/9. Selon le mode de fonctionnement de votre application, il peut être nécessaire de définir Multi-Release sur true dans le fichier jar. Cela est vrai pour les bocaux Spring Boot. Sans support multi-release, vous utiliserez la version antérieure à Java 9 de StackLocator, qui essaie d'utiliser Reflection.getCallerClass (). Cette classe a été supprimée en Java 9. Log4j utilisera une méthode plus lente pour calculer les emplacements de la pile, mais fonctionnera toujours. D'où l'avertissement.

1
rgoers