[ 
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$AppClassLoader@7c9ed5d6 finds 
false
Thread.currentThread().getContextClassLoader() 
sun.misc.Launcher$AppClassLoader@7c9ed5d6 finds false
ClassLoader.getSystemClassLoader() sun.misc.Launcher$AppClassLoader@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$AppClassLoader@7c9ed5d6
{quote}

as an output. Which looks to me like Log4j2 is using the parent classloader 
"AppClassLoader@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$AppClassLoader@7c9ed5d6 finds 
false
Thread.currentThread().getContextClassLoader() 
sun.misc.Launcher$AppClassLoader@7c9ed5d6 finds false
ClassLoader.getSystemClassLoader() sun.misc.Launcher$AppClassLoader@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$AppClassLoader@7c9ed5d6
{quote}

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

Does that give you enough detail?

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

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to