ClassLoaderFilter - Help

Help
matthew
2007-09-07
2013-04-17
  • matthew
    matthew
    2007-09-07

    Hi,

    I'm a University student from Australia and part of my current team project is to look at the internal workings of an opensource program, we choose JIP. Reverse engineering, basic UML diagrams, describe program flow etc...

    We are understanding most of it, and are really impressed with how it all works.  ASM libraries... wow!

    I was hoping that someone might be able to help our understanding in a few area's.  The biggest thing I am having trouble with is understanding what the com.mentorgen.tools.instrument.clfilter package does (especially the ClassLoaderFilter).  I have read the documentation, but seem unable to grasp what is happening.

    Any help in this area, and in any other JIP areas would be really appreciated!

    *sobs* Have pity on poor uni students...

     
    • Andrew Wilcox
      Andrew Wilcox
      2007-09-08

      Hi,

      I'd be happy to help you out! I'm going to assume that you've already read doc/classloader.html, but were confused because it's so poorly written :(

      Background: in Java classes are loaded by classloaders. In fact, there is a hierarchy of classloaders that looks like this:

      Bootstrap
          |
      Extensions
          |
      Application

      The bootstrap classloader loads the core classes that are part of the JDK. Classes in the java.* and sun.* packages fall into this category. The extensions classloader loads standard extensions (http://java.sun.com/j2se/1.5.0/docs/guide/extensions/spec.html), which are either in $JAVA_HOME/lib/ext or are specified with the -Djava.ext.dirs=... JVM argument. The application classloader loads the classes that are in the classpath. This is how standalone applications work, however containers like Tomcat or JBoss are a little more complicated, so I'll address those later on.

      The important thing to realize is that the classloader hierarchy limits visibility. Classes loaded higher in the hierarchy cannot reference classes that are loaded lower in the class loader hierarchy. For example, while classes loaded by the Application Classloader can "see" classes that are loaded by the other two classloaders, a class that is loaded by the Extensions classloader cannot "see" classes that are loaded by the Application classloader, and bootstrap classes cannot see classes loaded by any of the other classloaders. JIP uses the Java Agent interface (-javaagent). Very important: Agent classes are loaded by the Application Classloader.

      In JIP, there are two distinct phases of operation, there's the instrumentation phase and the runtime phase. In the instrumentation phase, JIP uses the (outstanding) ASM library to modify classes as they are classloaded to call JIP's runtime classes which collect performance data. In the instrumentation phase, JIP has the opportunity to modify classes that are loaded by _any_ of the  classloaders.  So when java.lang.String is loaded by the Bootstrap classloader, JIP can stick in a call to JIP's own runtime classes. You can probably see the problem with this: JIP is inserting a call to one of it's own classes and we know that JIP's classes are loaded by the application classloader, which is not visible to classes like java.lang.String because they are loaded by the Bootstrap classloader. In this case, you'd get a ClassNotFoundException.

      The ClassLoaderFilter interface has two methods:
         boolean accept(ClassLoader loader);
         boolean canFilter();

      The accept() method gets called in the instrumentation phase to find out if a class that is loaded by the given classloader should be instrumented. In a standalone application, the answer should be 'yes' if the classloader is the application classloader and 'no' otherwise. You can find out the which class is that application classloader by calling ClassLoader.getSystemClassLoader(). This always struck me as being somewhat counter-intuitive! So why have a ClassLoaderFilter? Just check to see if the Classloader is the application classloader and you're done! Well, not quite.

      Things get a little trickier when you're running in a container like the Tomcat Servlet engine. In Tomcat, the Application Classloader loads the classes that run the container itself. The classes that are packaged in your WAR file are loaded by another classloader that's further down in the classloader hierarchy. So if you're using JIP to profile a web application, you need a different ClassLoaderFilter that looks for the classloader that Tomcat uses to load webapp classes. If you're trying to use JIP in an environment that's not supported out of the box, you need to figure out which classloader is being used. There's a section in the 'FAQ' of doc/readme.html called "How can I control which classes and packages JIP profiles?" that tells you a little about how to do that.

      You're probably still wondering why ClassLoaderFilter.canFilter() is needed and what ClassLoaderFilter.1 and ClassLoaderFilter.2 in the profile.properties file do.

      The canFilter() method was designed to look at the running JVM's environment to determine if the particular ClassLoaderFilter is appropriate. So the WebAppClassLoaderFilter looks for the System property "catalina.home". If it's there, then Tomcat is being used, if not, then this ClassLoaderFilter shouldn't be used.

      The reason for specifying a list of ClassLoaderFilters in the profile.properties file is that JIP goes through them one by one and asks if they are appropriate for the current running environment. The idea being that you could have a single profile.properties file and use it for profiling standalone as well as web applications. The problem with that is that you really do want a different profile properties file for different environments. Standalone apps are usually not profiled interactively, while web apps are always profiled that way, and this behavior is controlled by the profile.properties file. Well, it seemed like a good idea at the time, but if I had it to do again, I'd only allow one ClassLoaderFilter. It would be much less confusing.

      I hope that I haven't overwhelmed you with too much information! Feel free to ask follow up questions if there is something you don't understand. The only dumb question is the one that you don't ask!

      Cheers,

      Andrew.

       
      • andyz
        andyz
        2007-09-13

        Thank you, Andrew. That was a concise and really informative explanation.

        Andy Z.

         
    • matthew
      matthew
      2007-09-10

      Wow!  Thank-you so much Andrew :) Took me most of today to figure it all out, but I am very impressed with how nicely it all fits together!  JIP is even more awesome than I thought!

      Shalom,

      Matthew

       
    • matthew
      matthew
      2007-09-10

      Just be looking at the other ClassLoaderFilter package net.sourceforge.jiprof.instrument.clfilter.  What is the Info filter ment to do.  I can see that it probably prints out debugging information, but when would you use it and why would that information be useful?

      Thank-you!

       
    • Andrew Wilcox
      Andrew Wilcox
      2007-09-11

      When you're dealing with an unsupported container, let's say GlassFish (https://glassfish.dev.java.net/), there are two pieces of information that you need to know in order to build a ClassLoaderFilter for that container: what classloader does it use for application classes and what system properties does it use the might be helpful in determining if the ClassLoaderFilter "canFilter". The Info ClassLoaderFilter was meant to help answer these questions. It prints out the current classloader and all of the system properties. You'll recall for my other post that if your running in Tomcat, that ClassLoaderFilter will look for the system property "catalina.home" to determine if Tomcat is running in the JVM.

      Unfortunately there is a flaw in the Info ClassLoaderFilter. JIP is always loaded by the same classloader -- the application classloader. If you're running in a container, your application classes (the ones in your WAR or EAR file) will _always_ be loaded by some other classloader. So in order to determine which classloader you really need to be filtering for, you need to put

      System.err.println(Thread.currentThread().getContextClassLoader().getClass().getName());

      in your application in order to figure which classloader it uses.

      The Info classloader filter is just a tool to help you get diagnostic info,

      BTW, when you guys are done with the docs that you are writing for your class, I'd like to be able to include them in the JIP distribution! All that I really require is that you license it under the Creative Commons license. If you decide to do that, just zip or tar them up and post them here on SourceForge as a 'patch'.

      Cheers,

      Andrew.

       
    • matthew
      matthew
      2007-09-13

      That would be really awesome!  We have done an earlier presentation on JIP (Powerpoint + speech) which you might personally interested in.  It is a big summary/history/feature presentation thingy.  If you're interested, is there an email address where you would like us to send it?

      Shalom,

       
      • Andrew Wilcox
        Andrew Wilcox
        2007-09-14

        I would be very interested to see your presentation! You can send it to awilcox32\at/yahoo.com.

        Andrew.

         
    • davy
      davy
      2009-06-06

      can i see the ppt also? 

      thank you.

      davy