I'm getting a StackOverFlowError in my project, as soon as it launches. I've seen other similar questions where the answer was that the lg4j.xml was not specifyed or uncorrectly formatted, but it does not seem to be the case here. This is the code:
public static void main( String[] args )
{
// Configure Logger
DOMConfigurator.configure("config/log4j.xml");
logger.info("Starting StudyImporter");
}
This is the log4j.xml file:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%d{yyyy-MM-dd HH:mm:ss,SSS} - [%t] %-5p %c %x - %m%n" />
</layout>
</appender>
<!-- log all logs to a separate log file every day -->
<appender name="MAIN_FA" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="C:/project/logs/main.log" />
<param name="datePattern" value="'-'yyyy-MM-dd'.log'" />
<param name="append" value="true" />
<!-- <param name="Threshold" value="INFO" /> -->
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %C{6} (%F:%L) - %m%n" />
</layout>
</appender>
<logger name="org.importadorestudios">
<level value="INFO" />
</logger>
<root>
<level value="INFO" />
<appender-ref ref="CONSOLE" />
<appender-ref ref="MAIN_FA" />
</root>
And this is the error:
java.lang.StackOverflowError
at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936)
at org.apache.log4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:39)
at org.apache.log4j.LogManager.getLogger(LogManager.java:45)
at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:64)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:285)
at org.apache.log4j.Category.<init>(Category.java:57)
at org.apache.log4j.Logger.<init>(Logger.java:37)
at org.apache.log4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:43)
at org.apache.log4j.LogManager.getLogger(LogManager.java:45)
at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:64)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:285)
at org.apache.log4j.Category.<init>(Category.java:57)
at org.apache.log4j.Logger.<init>(Logger.java:37)
at org.apache.log4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:43)
at org.apache.log4j.LogManager.getLogger(LogManager.java:45)
at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:64)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:285)
at org.apache.log4j.Category.<init>(Category.java:57)
Any help is greatly appreciated
To elaborate on my comment, SLF4J is a logging facade. This means that all it provides is some interfaces and a handful of helper classes to smooth things out behind the scenes. To actually use it you need to pick a logging implementation.
There are many implementations to choose from, but the most notable are:
When you pick an implementation, you typically also need a binding from SLF4J to that implementation and bridges from the other logging APIs to SLF4J. The existence of those bridges is the biggest reason to use SLF4J, as then you can route all of your app's own and its dependencies' logging into one implementation. There's even support for java.util.logging to get forwarded to SLF4J.
The key point though is that you cannot have the binding and the bridge for the same implementation on the classpath at the same time. Otherwise, you get what you see here: a stack overflow because the bridge is calling SLF4J which is calling the binding which is calling the bridge. Unfortunately, the ecosystem and the pitfalls are not always widely understood, and sometimes people do the wrong thing when distributing their software. For example, a published library should never pull in bindings or bridges. A library should only depend on the SLF4J API. It is only a finished application, or the test cases for a library, that should pick an implementation and thus pull in a binding (if necessary) and bridges for the other logging APIs.
These are bindings:
These are bridges:
java.util.logging to SLF4JThere's no logback bridge because logback's "native" API overlaps with SLF4J.
When using SLF4J, you want to pick one of the implementations. Then you include all of the following:
And you want to exclude all of the following if any of your transitive dependencies try to pull them in:
You can set up exclusions in both Maven and Gradle.
The problem was that there was a conflict between some of the libraries used by the project.
Apparently, someone once used another loggin library (slf4j) wich we no longer use. We removed the library from the pom.xml, but it was already downloaded in our computers. That caused the conflict wich generated the StackOverflowError.
To solve it, simply delete the unnecesary loggin library.
Thanks to talex for pointing in the right direction
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With