Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Back to your Class roots, continued

Find runtime origins for <em>all</em> loaded classes

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone

July 25, 2003

QCan you find the complete set of loaded classes from within a Java program and then determine from which file each class was loaded?

A This is another frequently asked Java question. Unfortunately, if you need an adequate solution for "real" product code, the answer is no. If, however, you don't mind something good enough for debugging and testing, then I show you a few tricks below.

From the previous Java Q&A installment, we know that given a Class object, you can usually trace it back to its origins, via the getClassLocation() method explained in that article.

Thus, we just need to find the set of classes currently loaded in the JVM. This, however, is the difficult part: The java.lang.ClassLoader API is not designed to provide any information about classes loaded by a given classloader instance, and Java classloaders are not required to register themselves in any programmatically accessible way. (A Sun Microsystems-compatible JVM will also show classes as they load if you use a -verbose:class JVM option. However, you cannot access this information programmatically.)

Let's tackle this problem in stages. I concentrate on pure Java ideas first and then mention other options later.

All classes loaded by a given classloader

It is not widely known that every java.lang.ClassLoader instance in a Sun-compatible Java 2 Platform, Standard Development Kit (J2SDK) has a private field that is a Vector of classes loaded and defined by that loader instance:

    /*
     * The classes loaded by this classloader. This table's only purpose
     * is to keep the classes from being garbage collected until the loader
     * is garbage collected.
     */
    private Vector classes = new Vector();


Observe that I say "defined" above: this is important. The classloader in question will not necessarily define every class requested via loadClass(): the class can get delegated to the loader's parent instead. Only the classes whose bytes are submitted to java.lang.ClassLoader.defineClass() by a given classloader instance shows up in its classes vector. Also, the JVM directly populates this field, so it always contains valid information (it even contains dynamically created classes such as dynamic proxies).

The following code (available with this article's download) exploits the information in the classes field:

public abstract class ClassScope
{
    public static Class [] getLoadedClasses (final ClassLoader loader)
    {
        if (loader == null) throw new IllegalArgumentException ("null input: loader");
        if (CLASSES_VECTOR_FIELD == null)
            throw new RuntimeException ("ClassScope::getLoadedClasses() cannot" +
            " be used in this JRE", CVF_FAILURE);
        
        try
        {
            final Vector classes = (Vector) CLASSES_VECTOR_FIELD.get (loader);
            if (classes == null) return EMPTY_CLASS_ARRAY;
            
            final Class [] result;
            
            // Note: Vector is synchronized in Java 2, which helps us make
            // the following into a safe critical section:
            
            synchronized (classes)
            {
                result = new Class [classes.size ()];
                classes.toArray (result);
            }
            
            return result;
        }
        // This should not happen if <clinit> was successful:
        catch (IllegalAccessException e)
        {
            e.printStackTrace (System.out);
            
            return EMPTY_CLASS_ARRAY;
        }
    }
    
    
    private static final Field CLASSES_VECTOR_FIELD; // Set in <clinit> [can be null]
    
    private static final Class [] EMPTY_CLASS_ARRAY = new Class [0];
    private static final Throwable CVF_FAILURE; // Set in <clinit>
    
    static
    {
        Throwable failure = null;
        
        Field tempf = null;
        try
        {
            // This can fail if this is not a Sun-compatible JVM
            // or if the security is too tight:
            
            tempf = ClassLoader.class.getDeclaredField ("classes");
            if (tempf.getType () != Vector.class)
                throw new RuntimeException ("not of type java.util.Vector: " +
                tempf.getType ().getName ());
            tempf.setAccessible (true);
        }
        catch (Throwable t)
        {
            failure = t;
        }
        CLASSES_VECTOR_FIELD = tempf;
        CVF_FAILURE = failure;
    }
} // End of class


Note that getLoadedClasses()'s result is a snapshot: the list of loaded classes varies depending on when you call the method. (The list grows over time, however, when the method is invoked on the same classloader instance.)

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comments (7)
Login
Forgot your account info?

CKJCFJK XFJFJU XJUTYJLOGUBy Anonymous on August 10, 2010, 1:07 pmhollister ukZSETVCTUHJZXEDCTYHXEDCFTJU hollister hollister clothing hollister clothes hollister london hollister sale hollister outlet hollister online

Reply | Read entire comment

jordan basketball shoesBy Anonymous on August 6, 2010, 4:45 amthevibram five fingers shoes bigvibram five fingers sale boyvibram fivefingers girl cheapvibram five fingers boysdiscount vibram five fingers fivevibram five fingers...

Reply | Read entire comment

DHZGJYTREWMFXSGT HDRGRFBy Anonymous on August 5, 2010, 11:21 amabercrombie uk abercrombie and fitch uk abercrombie fitch uk Abercrombie & fitch uk JYHJUYHJUMKTRUYUJHYKIU‘?’PO‘?OP?’/PO??O

Reply | Read entire comment

jBy Anonymous on July 2, 2010, 7:32 amjkjk

Reply | Read entire comment

So, where is the comment?By undereyecreams on June 7, 2010, 12:07 amSo, where is the comment?

Reply | Read entire comment

View all comments

Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.
Archived Discussions (Read only)
Subject
. Forum migration complete By AthenAdministrator
. Forum migration update By AthenAdministrator
. nice By Anonymous
Resources