LogManager.getLogger() is unable to determine class name on Java 11 [duplicate]
Asked Answered
P

2

34

I'm using log4j2 (2.11.1) with Java 11 and attempting to get a Logger object using:

private static final Logger LOG = LogManager.getLogger();

(Imported from log4j-api in org.apache.logging.log4j)

At runtime, I receive the following error:

WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.UnsupportedOperationException: No class provided, and an appropriate one cannot be found.
at 
org.apache.logging.log4j.LogManager.callerClass(LogManager.java:555)
    at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:580)
    at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:567)
    at app.App.<clinit>(App.java:11)

Which does make sense - getCallerClass is not supported and so the logger is unable to determine the class name.

Is it supposed to work this way? Surely I don't have to hard-code the class name into each logger?

Ploughshare answered 23/10, 2018 at 16:6 Comment(10)
There's been some "clean up" in the Java API and underlying system code. My guess is something that used to work doesn't anymore, and the Apache folks haven't got around to fixing it. I don't know what you can do other than downgrade to an earlier version of Java or use a different log manager.Superclass
Could you be precise over which dependency of log4j2 (2.11.1)?Subdeacon
It's log4j-api - edited question to includePloughshare
@Superclass wow, really? One of the most popular logging frameworks isn't compatible with current LTS of Java?Ploughshare
@DanielScott I find that third party efforts to outdo existing standard functionality tend to believe their “clever” hacks are what make them superior. I don’t share their belief.Marinara
The official API, StackWalker.getCallerClass(), has been introduced with Java 9. According to the changelogs, support for it has been added even in log4j2 2.9.0. Perhaps, you need a build specifically for Java 9+…Crow
When I download pre-built binaries from logging.apache.org/log4j/2.x/download.html I get multi-release jars, which will automatically select the implementation version when running under Java 9 or newer. So the crucial point is how the version, you are using, has been built.Crow
@Crow is right mostly, seems like you're not using the library under java9+ which is where the updated implementation of StackLocator is. Not able to share a screenshot here in the comments, but the MR-JAR of log4j includes a different implementation of StackLocator at ../.m2/repository/org/apache/logging/log4j/log4j-api/2.11.1/log4j-api-2.11.1.jar!/META-INF/versions/9/org/apache/logging/log4j/util/StackLocator.classSubdeacon
Yep, I have that class file in my dependency... still not working thoughPloughshare
And the file is identical to the one in the same location in my shaded jarPloughshare
P
35

The reason was that the multi-release class files were not being picked up from META-INF/versions/* because I hadn't set the multi-release flag when I built my shaded jar.

I needed to add:

Multi-Release:true

To my manifest, and everything started working.

Ploughshare answered 23/10, 2018 at 19:45 Comment(7)
Yep, I shouldn't have forgotten as well that log4j is a multi-release jarSubdeacon
@Daniel - Can you expand on that? Which manifest did you add that line to? I don't get what "shaded jar" is.Mohican
A 'shared' jar is a jar which repackages your code with it's dependencies. It's the manifest in this jar which contains the additional linePloughshare
@DanielScott so every jar which calls logmanager getlogger should be a multi-release jar if it uses log4j 2.11?Archaism
Best to test that yourself, but I expect that as long as the jar you've built is multi-release and it includes log4j it should be finePloughshare
@DanielScott this solution still not working with jdk14 and log4j2 (2.13.2) . I tried to insert the property in the manifest Multi-Release:true as property but the same error appear. There same changes with the new log4j2 ?Organ
Are you certain it's present in the manifest? Did you unpack the jar to check?Ploughshare
E
14

The answer by @DanielScott is correct. When using the Gradle Shadow plugin, I added the following to my build.gradle to appended the Multi-Release:true flag to the manifest.

jar {
    manifest {
        attributes 'Multi-Release': 'true'
    }
}
Etan answered 6/8, 2019 at 16:35 Comment(2)
This worked for me, running on Amazon Corretto 15.Francenefrances
Same thing on Maven can be accomplished by adding <manifestEntries><Multi-Release>true</Multi-Release></manifestEntries> in the <archive> tag of your pom.xmlNeveda

© 2022 - 2024 — McMap. All rights reserved.