Search code examples
javalog4jjava-web-startslf4jlogback

how to find out which jar is being loaded for slf4j


I have a really strange problem in a Java webstart application. I'm using slf4j and logback for my logging framework but when one of my users runs the webstart application he gets a log4j warning message! I'm not including log4j jars in the webstart application. Where can log4j possibly be coming from and how do I find out? I cannot import any log4j classes and call their methods because I cannot compile against a jar file I don't have.

Here are some details:

slf4j 1.7.12 logback classic and core 1.1.3

The main class looks something like this:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyMain {

    static {
        String classpath = System.getProperty("java.class.path");
        System.out.println("CLASSPATH = " + classpath);
    }

    private final static Logger LOG = LoggerFactory.getLogger(MyMain.class);

    public void static main( String args[] ) {
        // do stuff...
    }

}

The output of this program on my user's Mac OS X Yosemite 10.10.3 is (remember it is a webstart program and there is a JNLP file that is launched from a browser):

CLASSPATH = /Library/Internet Plugins/JavaAppletPlugin.plugin/Contents/Home/lib/deploy.jar
log4j:WARN No appenders could be found for logger (MyMain).
log4j:WARN Please initialize the log4j system properly.

Here is the JNLP file:

<jnlp spec="6.0" codebase="http://example.com/mymain">
  <information>
    <title>MyMain</title>
    <vendor>My Business</vendor>
    <homepage href="http://www.example.com"/>
    <description>My Application</description>
    <description kind="short">GUI Tool</description>
    <icon href="resources/your.appicon.gif"/>
    <icon kind="splash" href="resources/your.splashicon.gif"/>
    <offline-allowed/>
  </information>
  <resources>
    <j2se version="1.8+" max-heap-size="1024M"/>
    <jar href="mymain.jar" main="true"/>
    <jar href="tsallperspectives63dep.jar"/>
    <jar href="activation-1.1.jar"/>
    <jar href="antlr-runtime.jar"/>
    <jar href="appframework-1.0.3.jar"/>
    <jar href="asm-all-repackaged-2.1.88.jar"/>
    <jar href="asm-all-repackaged-2.2.0-b21.jar"/>
    <jar href="batik.jar"/>
    <jar href="beansbinding-1.2.1.jar"/>
    <jar href="cglib-2.1.88.jar"/>
    <jar href="cglib-2.2.0-b21.jar"/>
    <jar href="common.jar"/>
    <jar href="commonj.sdo-2.1.1.jar"/>
    <jar href="commons-beanutils-1.8.3.jar"/>
    <jar href="commons-codec-1.6.jar"/>
    <jar href="commons-lang3-3.4.jar"/>
    <jar href="commons-logging-1.1.3.jar"/>
    <jar href="derbyclient.jar"/>
    <jar href="dom4j-1.6.1.jar"/>
    <jar href="eclipselink-2.5.0.jar"/>
    <jar href="guava-14.0.1.jar"/>
    <jar href="hk2-api-2.1.88.jar"/>
    <jar href="hk2-api-2.2.0-b21.jar"/>
    <jar href="hk2-locator-2.1.88.jar"/>
    <jar href="hk2-locator-2.2.0-b21.jar"/>
    <jar href="hk2-utils-2.1.88.jar"/>
    <jar href="hk2-utils-2.2.0-b21.jar"/>
    <jar href="httpclient-4.3.5.jar"/>
    <jar href="httpcore-4.3.2.jar"/>
    <jar href="iText.jar"/>
    <jar href="javaee-api-7.0.jar"/>
    <jar href="javax.annotation-api-1.2.jar"/>
    <jar href="javax.inject-1.jar"/>
    <jar href="javax.inject-2.1.88.jar"/>
    <jar href="javax.inject-2.2.0-b21.jar"/>
    <jar href="javax.mail-1.5.0.jar"/>
    <jar href="javax.persistence-2.1.0.jar"/>
    <jar href="javax.ws.rs-api-2.0.jar"/>
    <jar href="jcommon-1.0.17.jar"/>
    <jar href="jersey-client-2.0.jar"/>
    <jar href="jersey-client-2.4.1.jar"/>
    <jar href="jersey-common-2.0.jar"/>
    <jar href="jersey-common-2.4.1.jar"/>
    <jar href="jfreechart-1.0.14.jar"/>
    <jar href="jfreesvg-2.1.jar"/>
    <jar href="jsse.jar"/>
    <jar href="jul-to-slf4j-1.7.12.jar"/>
    <jar href="junit-3.8.1.jar"/>
    <jar href="logback-classic-1.1.3.jar"/>
    <jar href="logback-core-1.1.3.jar"/>
    <jar href="ojdbc6.jar"/>
    <jar href="ojpse.jar"/>
    <jar href="oraclepki.jar"/>
    <jar href="oraclepki103.jar"/>
    <jar href="osdt_cert.jar"/>
    <jar href="osdt_core.jar"/>
    <jar href="osgi-resource-locator-1.0.1.jar"/>
    <jar href="poi.jar"/>
    <jar href="serializer.jar"/>
    <jar href="slf4j-api-1.7.12.jar"/>
    <jar href="sso.jar"/>
    <jar href="swing-layout-1.0.4.jar"/>
    <jar href="swing-worker-1.1.jar"/>
    <jar href="xalan.jar"/>
    <jar href="xmlbeans-2.3.0.jar"/>
  </resources>
  <application-desc main-class="MyMain">
    <argument>-h</argument>
    <argument>example.com</argument>
    <argument>-u</argument>
    <argument>user</argument>
    <argument>-p</argument>
    <argument>pass</argument>
  </application-desc>
  <security>
    <all-permissions/>
  </security>
</jnlp>

Note, there is a commons-logging jar that is a transitive dependency of some other jar (I'm not sure which). I don't think this is related.

Now, I also have Mac OS X Yosemite 10.10.3 and I do not get any warning from log4j... I get what I expect for output:

CLASSPATH = /Library/Internet Plug-ins/JavaAppletPlugin.plugin/Contents/Home/lib/deploy.jar
20:51:43,748 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
20:51:43,750 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
20:51:43,750 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [jar:http://example.com/mymain/mymain.jar!/logback.xml]

I know of two other Mac OS X systems that properly run this webstart app and no others that fail like this one user's system.

All systems are running Java 1.8.0 update 45.

The only possible thing I can think of is that my user's system has some other java application that has installed log4j in a location that is loaded on the classpath or by Java webstart and this is loading before my webstart application. Possibly this jar is in /Library/Java/Extensions or ~/Library/Java/Extensions.

How do I find out where this log4j message is coming from? As in... which jar file and where is that jar file stored on the filesystem?


Solution

  • To find out what jar or classpath entry has the slf4j bridge/implementation use the following code in your MyMain.

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.slf4j.ILoggerFactory;
    
    public class MyMain {
    
        static {
            ILoggerFactory lf = binder.getLoggerFactory();
            Class lfc = lf.getClass();
            System.out.println(lfc.getResource(lfc.getSimpleName() + ".class"));
        }
    
        private final static Logger LOG = LoggerFactory.getLogger(MyMain.class);
    
        public void static main( String args[] ) {
            // do stuff...
        }
    
    }