Discussion:
[jira] [Created] (LOG4J2-862) Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
Michael Sutherland (JIRA)
2014-09-26 04:09:33 UTC
Permalink
Michael Sutherland created LOG4J2-862:
-----------------------------------------

Summary: Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland


In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.

The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.

I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading




--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Remko Popma (JIRA)
2014-09-26 06:29:33 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14148833#comment-14148833 ]

Remko Popma commented on LOG4J2-862:
------------------------------------

Thanks for pointing out this possibility.
The current message was introduced based on frequent questions on StackOverflow, but perhaps we can refine the wording a little.

Can you explain the scenario that caused ProviderUtil to use a different Classloader than the rest of your application?
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Michael Sutherland (JIRA)
2014-09-26 06:55:34 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14148850#comment-14148850 ]

Michael Sutherland commented on LOG4J2-862:
-------------------------------------------

I can give a rough explaination now but I haven't had the oportunity to refine it down to the bare details so some of the information may be extraneous. I'm also having to obfuscate some company specific details so you may see some cut and paste artifacts.

I have an Ant script that calls a

{code:title=build.xml|borderStyle=solid}
<project name="DB 1.0.0" default="build">

<path id="project.classpath">
<fileset dir="$./lib/shipped">
<include name="log4j-1.2-api-2.0.2.jar"/>
<include name="log4j-api-2.0.2.jar"/>
<include name="log4j-core-2.0.2.jar"/>
</fileset>
<path location="./classes"/>
</path>

<taskdef name="customTaskThatUsesLog4j" classname="com.example.CustomTaskThatUsesLog4j">
<classpath refid="project.classpath"/>
</taskdef>
<customTaskThatUsesLog4j hostname="zzzz" username="suthermi"/>
</build>
{code}


The customTaskThatUsesLog4j should print out a number of messages about what it's doing using Log4j2 but fails due to the errors mentioned above. If I add the following code to the task

{code:title=CustomTaskThatUsesLog4j.java|borderStyle=solid}
String recName = "META-INF/log4j-provider.properties";
System.out.println("ProviderUtil.findClassLoader() "+ProviderUtil.findClassLoader()+" finds "+ProviderUtil.findClassLoader().getResources(recName).hasMoreElements());
System.out.println("Thread.currentThread().getContextClassLoader() "+Thread.currentThread().getContextClassLoader()+" finds "+Thread.currentThread().getContextClassLoader().getResources(recName).hasMoreElements());
System.out.println("ClassLoader.getSystemClassLoader() "+ClassLoader.getSystemClassLoader()+" finds "+ClassLoader.getSystemClassLoader().getResources(recName).hasMoreElements());
System.out.println("ProviderUtil.class.getClassLoader() "+ProviderUtil.class.getClassLoader()+" finds "+ProviderUtil.class.getClassLoader().getResources(recName).hasMoreElements());
System.out.println("ProviderUtil.class.getClassLoader() parent "+ProviderUtil.class.getClassLoader().getParent());
{code}

I get

{quote}
ProviderUtil.findClassLoader() sun.misc.Launcher$***@7c9ed5d6 finds false
Thread.currentThread().getContextClassLoader() sun.misc.Launcher$***@7c9ed5d6 finds false
ClassLoader.getSystemClassLoader() sun.misc.Launcher$***@7c9ed5d6 finds false
ProviderUtil.class.getClassLoader() AntClassLoader[.\log4j-core-2.0.2.jar;.\lib\shipped\commons-lang-2.5.jar;.\lib\shipped\log4j-1.2-api-2.0.2.jar;.\lib\shipped\log4j-api-2.0.2.jar;.\classes] finds true
ProviderUtil.class.getClassLoader() parent sun.misc.Launcher$***@7c9ed5d6
{quote}

as an output. Which looks to me like Log4j2 is using the parent classloader "***@7c9ed5d6" of the class loader it should be using "AntClassLoader".

Does that give you enough detail?
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Michael Sutherland (JIRA)
2014-09-26 06:58:33 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14148850#comment-14148850 ]

Michael Sutherland edited comment on LOG4J2-862 at 9/26/14 6:57 AM:
--------------------------------------------------------------------

I can give a rough explaination now but I haven't had the oportunity to refine it down to the bare details so some of the information may be extraneous. I'm also having to obfuscate some company specific details so you may see some cut and paste artifacts.

I have an Ant script that calls a custom Ant task

{code:title=build.xml|borderStyle=solid}
<project name="DB 1.0.0" default="build">

<path id="project.classpath">
<fileset dir="$./lib/shipped">
<include name="log4j-1.2-api-2.0.2.jar"/>
<include name="log4j-api-2.0.2.jar"/>
<include name="log4j-core-2.0.2.jar"/>
</fileset>
<path location="./classes"/>
</path>

<taskdef name="customTaskThatUsesLog4j" classname="com.example.CustomTaskThatUsesLog4j">
<classpath refid="project.classpath"/>
</taskdef>
<customTaskThatUsesLog4j hostname="zzzz" username="suthermi"/>
</build>
{code}


The customTaskThatUsesLog4j should print out a number of messages about what it's doing using Log4j2 but fails due to the errors mentioned above. If I add the following code to the task

{code:title=CustomTaskThatUsesLog4j.java|borderStyle=solid}
String recName = "META-INF/log4j-provider.properties";
System.out.println("ProviderUtil.findClassLoader() "+ProviderUtil.findClassLoader()+" finds "+ProviderUtil.findClassLoader().getResources(recName).hasMoreElements());
System.out.println("Thread.currentThread().getContextClassLoader() "+Thread.currentThread().getContextClassLoader()+" finds "+Thread.currentThread().getContextClassLoader().getResources(recName).hasMoreElements());
System.out.println("ClassLoader.getSystemClassLoader() "+ClassLoader.getSystemClassLoader()+" finds "+ClassLoader.getSystemClassLoader().getResources(recName).hasMoreElements());
System.out.println("ProviderUtil.class.getClassLoader() "+ProviderUtil.class.getClassLoader()+" finds "+ProviderUtil.class.getClassLoader().getResources(recName).hasMoreElements());
System.out.println("ProviderUtil.class.getClassLoader() parent "+ProviderUtil.class.getClassLoader().getParent());
{code}

I get

{quote}
ProviderUtil.findClassLoader() sun.misc.Launcher$***@7c9ed5d6 finds false
Thread.currentThread().getContextClassLoader() sun.misc.Launcher$***@7c9ed5d6 finds false
ClassLoader.getSystemClassLoader() sun.misc.Launcher$***@7c9ed5d6 finds false
ProviderUtil.class.getClassLoader() AntClassLoader[.\log4j-core-2.0.2.jar;.\lib\shipped\commons-lang-2.5.jar;.\lib\shipped\log4j-1.2-api-2.0.2.jar;.\lib\shipped\log4j-api-2.0.2.jar;.\classes] finds true
ProviderUtil.class.getClassLoader() parent sun.misc.Launcher$***@7c9ed5d6
{quote}

as an output. Which looks to me like Log4j2 is using the parent classloader "***@7c9ed5d6" of the class loader it should be using "AntClassLoader".

Does that give you enough detail?


was (Author: mike1979):
I can give a rough explaination now but I haven't had the oportunity to refine it down to the bare details so some of the information may be extraneous. I'm also having to obfuscate some company specific details so you may see some cut and paste artifacts.

I have an Ant script that calls a

{code:title=build.xml|borderStyle=solid}
<project name="DB 1.0.0" default="build">

<path id="project.classpath">
<fileset dir="$./lib/shipped">
<include name="log4j-1.2-api-2.0.2.jar"/>
<include name="log4j-api-2.0.2.jar"/>
<include name="log4j-core-2.0.2.jar"/>
</fileset>
<path location="./classes"/>
</path>

<taskdef name="customTaskThatUsesLog4j" classname="com.example.CustomTaskThatUsesLog4j">
<classpath refid="project.classpath"/>
</taskdef>
<customTaskThatUsesLog4j hostname="zzzz" username="suthermi"/>
</build>
{code}


The customTaskThatUsesLog4j should print out a number of messages about what it's doing using Log4j2 but fails due to the errors mentioned above. If I add the following code to the task

{code:title=CustomTaskThatUsesLog4j.java|borderStyle=solid}
String recName = "META-INF/log4j-provider.properties";
System.out.println("ProviderUtil.findClassLoader() "+ProviderUtil.findClassLoader()+" finds "+ProviderUtil.findClassLoader().getResources(recName).hasMoreElements());
System.out.println("Thread.currentThread().getContextClassLoader() "+Thread.currentThread().getContextClassLoader()+" finds "+Thread.currentThread().getContextClassLoader().getResources(recName).hasMoreElements());
System.out.println("ClassLoader.getSystemClassLoader() "+ClassLoader.getSystemClassLoader()+" finds "+ClassLoader.getSystemClassLoader().getResources(recName).hasMoreElements());
System.out.println("ProviderUtil.class.getClassLoader() "+ProviderUtil.class.getClassLoader()+" finds "+ProviderUtil.class.getClassLoader().getResources(recName).hasMoreElements());
System.out.println("ProviderUtil.class.getClassLoader() parent "+ProviderUtil.class.getClassLoader().getParent());
{code}

I get

{quote}
ProviderUtil.findClassLoader() sun.misc.Launcher$***@7c9ed5d6 finds false
Thread.currentThread().getContextClassLoader() sun.misc.Launcher$***@7c9ed5d6 finds false
ClassLoader.getSystemClassLoader() sun.misc.Launcher$***@7c9ed5d6 finds false
ProviderUtil.class.getClassLoader() AntClassLoader[.\log4j-core-2.0.2.jar;.\lib\shipped\commons-lang-2.5.jar;.\lib\shipped\log4j-1.2-api-2.0.2.jar;.\lib\shipped\log4j-api-2.0.2.jar;.\classes] finds true
ProviderUtil.class.getClassLoader() parent sun.misc.Launcher$***@7c9ed5d6
{quote}

as an output. Which looks to me like Log4j2 is using the parent classloader "***@7c9ed5d6" of the class loader it should be using "AntClassLoader".

Does that give you enough detail?
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Remko Popma (JIRA)
2014-09-26 08:35:33 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14148915#comment-14148915 ]

Remko Popma commented on LOG4J2-862:
------------------------------------

I had a look at the code. Looks like ProviderUtil uses the current Thread classloader, unless the Security Manager restricts the "getClassLoader" privilege, in which case it uses the classloader of its own class. We probably want the latter, so you could try restricting that permission.

You may be able to get more detail on what is going wrong by setting system property {{-Dlog4j2.StatusLogger.level=TRACE}} - this is the internal log4j2 status logging level before it is set to the status level of the log4j2.xml configuration file.
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Michael Sutherland (JIRA)
2014-09-26 09:11:33 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14148950#comment-14148950 ]

Michael Sutherland commented on LOG4J2-862:
-------------------------------------------

I did try setting "-Dlog4j2.StatusLogger.level=TRACE" but Log4j2 fails with the class cast exception before it starts logging anything so it doesn't add anything to the discussion.

When you say "Looks like ProviderUtil uses the current Thread classloader, unless the Security Manager restricts the "getClassLoader" privilege, in which case it uses the classloader of its own class." I don't think I agree, if it cannot use "ThreadContextClassLoaderGetter" it uses "ClassLoader.getSystemClassLoader()" which is not the same as "ProviderUtil.class.getClassLoader()". You can see the output from the three different options in the code I quoted above. In short "ClassLoader.getSystemClassLoader()" will return an instance of "Launcher$AppClassLoader" and "ProviderUtil.class.getClassLoader()" will return an instance of "AntClassLoader"
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Michael Sutherland (JIRA)
2014-09-26 09:18:34 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14148950#comment-14148950 ]

Michael Sutherland edited comment on LOG4J2-862 at 9/26/14 9:18 AM:
--------------------------------------------------------------------

I did try setting _"-Dlog4j2.StatusLogger.level=TRACE"_ but Log4j2 fails with the class cast exception before it starts logging anything so it doesn't add anything to the discussion.

When you say "Looks like ProviderUtil uses the current Thread classloader, unless the Security Manager restricts the "getClassLoader" privilege, in which case it uses the classloader of its own class." I don't think I agree, if it cannot use {code}ThreadContextClassLoaderGetter{code} it uses {code}ClassLoader.getSystemClassLoader(){code} which is not the same as {code}ProviderUtil.class.getClassLoader(){code}.

You can see the output from the three different options in the code I quoted above. In short {code}ClassLoader.getSystemClassLoader(){code} will return an instance of {code}sun.misc.Launcher$AppClassLoader{code} and {code}ProviderUtil.class.getClassLoader(){code} will return an instance of {code}AntClassLoader{code}

How do you do the format for the -DLog4j line? It would make this post much clearer to read.







was (Author: mike1979):
I did try setting "-Dlog4j2.StatusLogger.level=TRACE" but Log4j2 fails with the class cast exception before it starts logging anything so it doesn't add anything to the discussion.

When you say "Looks like ProviderUtil uses the current Thread classloader, unless the Security Manager restricts the "getClassLoader" privilege, in which case it uses the classloader of its own class." I don't think I agree, if it cannot use "ThreadContextClassLoaderGetter" it uses "ClassLoader.getSystemClassLoader()" which is not the same as "ProviderUtil.class.getClassLoader()". You can see the output from the three different options in the code I quoted above. In short "ClassLoader.getSystemClassLoader()" will return an instance of "Launcher$AppClassLoader" and "ProviderUtil.class.getClassLoader()" will return an instance of "AntClassLoader"
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Remko Popma (JIRA)
2014-09-26 10:07:34 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14148996#comment-14148996 ]

Remko Popma commented on LOG4J2-862:
------------------------------------

Surround the string with \{\{ and \}\}
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Michael Sutherland (JIRA)
2014-09-26 10:11:33 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14148950#comment-14148950 ]

Michael Sutherland edited comment on LOG4J2-862 at 9/26/14 10:11 AM:
---------------------------------------------------------------------

I did try setting _"-Dlog4j2.StatusLogger.level=TRACE"_ but Log4j2 fails with the class cast exception before it starts logging anything so it doesn't add anything to the discussion.

When you say "Looks like ProviderUtil uses the current Thread classloader, unless the Security Manager restricts the "getClassLoader" privilege, in which case it uses the classloader of its own class." I don't think I agree, if it cannot use {{ThreadContextClassLoaderGetter}} it uses {{ClassLoader.getSystemClassLoader()}} which is not the same as {{ProviderUtil.class.getClassLoader()}}.

You can see the output from the three different options in the code I quoted above. In short {{ClassLoader.getSystemClassLoader()}} will return an instance of {{sun.misc.Launcher$AppClassLoader}} and {{ProviderUtil.class.getClassLoader()}} will return an instance of {{AntClassLoader}}

How do you do the format for the -DLog4j line? It would make this post much clearer to read.







was (Author: mike1979):
I did try setting _"-Dlog4j2.StatusLogger.level=TRACE"_ but Log4j2 fails with the class cast exception before it starts logging anything so it doesn't add anything to the discussion.

When you say "Looks like ProviderUtil uses the current Thread classloader, unless the Security Manager restricts the "getClassLoader" privilege, in which case it uses the classloader of its own class." I don't think I agree, if it cannot use {code}ThreadContextClassLoaderGetter{code} it uses {code}ClassLoader.getSystemClassLoader(){code} which is not the same as {code}ProviderUtil.class.getClassLoader(){code}.

You can see the output from the three different options in the code I quoted above. In short {code}ClassLoader.getSystemClassLoader(){code} will return an instance of {code}sun.misc.Launcher$AppClassLoader{code} and {code}ProviderUtil.class.getClassLoader(){code} will return an instance of {code}AntClassLoader{code}

How do you do the format for the -DLog4j line? It would make this post much clearer to read.
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Remko Popma (JIRA)
2014-09-26 11:06:34 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14148996#comment-14148996 ]

Remko Popma edited comment on LOG4J2-862 at 9/26/14 11:06 AM:
--------------------------------------------------------------

Surround the string with \{\{ and \}\}.

Hmm... Just looking at the LoaderUtil code, if a SecurityManager is set, and RuntimePermission("getClassLoader") is not permitted, then internal flag GET_CLASS_LOADER_DISABLED is set, and getThreadContextClassLoader() returns LoaderUtil.class.getClassLoader().

The ThreadContextClassLoaderGetter you mentioned only comes into play if the internal flag GET_CLASS_LOADER_DISABLED is false.


was (Author: ***@yahoo.com):
Surround the string with \{\{ and \}\}
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Matt Sicker (JIRA)
2014-09-26 21:08:33 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Matt Sicker reassigned LOG4J2-862:
----------------------------------

Assignee: Matt Sicker
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
Assignee: Matt Sicker
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Matt Sicker (JIRA)
2014-09-26 21:09:33 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Matt Sicker resolved LOG4J2-862.
--------------------------------
Resolution: Fixed
Fix Version/s: 2.1

Pushed a fix. I had mixed up the order of ClassLoader priority in the class.
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
Assignee: Matt Sicker
Fix For: 2.1
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Remko Popma (JIRA)
2014-09-26 23:22:33 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14150183#comment-14150183 ]

Remko Popma commented on LOG4J2-862:
------------------------------------

Thanks Matt! Can you add an entry to changes.xml for the release notes?

Michael, can you build from master and confirm that this solves the issue? Thanks!
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
Assignee: Matt Sicker
Fix For: 2.1
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Remko Popma (JIRA)
2014-09-27 13:55:34 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14150591#comment-14150591 ]

Remko Popma commented on LOG4J2-862:
------------------------------------

(Updated change log.)

Michael, we are getting ready for the 2.1 release. If the fix in master does not work we just might be able to correct it if you let us know soon.
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
Assignee: Matt Sicker
Fix For: 2.1
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Michael Sutherland (JIRA)
2014-09-29 04:34:33 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Michael Sutherland reopened LOG4J2-862:
---------------------------------------

I've tried building from trunk and I'd say this is still a problem. I think it's due to ProviderUtil.findClassLoader going directly to LoaderUtil.getThreadContextClassLoader(). It means all the code in LoaderUtil that checks for the "IGNORE_TCCL_PROPERTY" is skipped and Thread.currentThread().getContextClassLoader() is exectuted despite the system properties.

If i replace the line {{if (cl != null){}} with {{if (cl != null && !"true".equals(System.getProperty(IGNORE_TCCL_PROPERTY))) {}} log4j works as I'd expect but it doesn't fit the architecture of having PropertiesUtil
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
Assignee: Matt Sicker
Fix For: 2.1
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Matt Sicker (JIRA)
2014-09-30 02:34:33 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Matt Sicker resolved LOG4J2-862.
--------------------------------
Resolution: Fixed

Fixed for real this time in the latest master.
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
Assignee: Matt Sicker
Fix For: 2.1
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Matt Sicker (JIRA)
2014-09-30 02:36:33 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14152729#comment-14152729 ]

Matt Sicker edited comment on LOG4J2-862 at 9/30/14 2:35 AM:
-------------------------------------------------------------

Fixed for real this time in the latest master. Commit ID: d80c6a20824bd13090bf80d415c02b39c53e8f21


was (Author: jvz):
Fixed for real this time in the latest master.
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
Assignee: Matt Sicker
Fix For: 2.1
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Michael Sutherland (JIRA)
2014-09-30 05:40:34 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14152820#comment-14152820 ]

Michael Sutherland commented on LOG4J2-862:
-------------------------------------------

Agreed, a build from master works perfectly now. Thanks Matt and Remko.
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
Assignee: Matt Sicker
Fix For: 2.1
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
Matt Sicker (JIRA)
2014-10-04 05:15:34 UTC
Permalink
[ https://issues.apache.org/jira/browse/LOG4J2-862?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Matt Sicker closed LOG4J2-862.
------------------------------

Thanks for the confirmation.
Post by Michael Sutherland (JIRA)
Misleading error message "Log4j2 could not find a logging implementation. Please add log4j-core to the classpath."
------------------------------------------------------------------------------------------------------------------
Key: LOG4J2-862
URL: https://issues.apache.org/jira/browse/LOG4J2-862
Project: Log4j 2
Issue Type: Bug
Components: Configurators
Affects Versions: 2.0.2
Reporter: Michael Sutherland
Assignee: Matt Sicker
Fix For: 2.1
In the code out put I see
"ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console..." followed by "java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext" which means core must be on the class path as otherwise you couldn't get that class cast execption. At which point the application using Log4j2 fails to start.
The underlying problem is org.apache.logging.log4j.LogManager assuming if org.apache.logging.log4j.util.ProviderUtil returns false for hasProviders it is because core is not on the classpath. In practice I've found that hasProviders can return false because ProviderUtil is using a different Classloader than the rest of the application. It cannot find the "META-INF/log4j-provider.properties" resource but it is on the class path.
I think there is a problem with the logic of how the classloaders are chosen but I don't understand what Log4j is trying to do here, however I am sure the error message is confusing and misleading
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Loading...