Utensil
Utensil

Reputation: 19643

Why can't java use thread context classloader when a method is literally called?

I've written a custom classloader 'JarClassLoader', which itself works ok, since the following test case is green:

public void testJarClassLoader() throws Exception
{
    JarClassLoader cl = new JarClassLoader();
    cl.addURLsByClassPath("lib/a-lot-of-jars.jar|lib/more-jars.jar", "\\|");

    Class c = cl.loadClass("com.packagepath.classname");

    assertNotNull(c);

    System.out.println("Class: "+ c);
}

But, the following test case would not work:

public void testSetThreadClassLoader() throws Exception
{
    JarClassLoader cl = new JarClassLoader();
    cl.addURLsByClassPath("lib/a-lot-of-jars.jar|lib/more-jars.jar", "\\|");

    Thread t = new Thread() {
        public void run()
        {
            TestCase.assertEquals("com.packagepath.JarClassLoader", 
                    Thread.currentThread().getContextClassLoader().getClass().getName());
            //this assertion passed


            try
            {
                Class c = Class.forName("com.packagepath.classname");

                //it doesn't work, throws ClassNotFoundException

                TestCase.assertNotNull(c);
            }
            catch (ClassNotFoundException e)
            {
                e.printStackTrace();
            }

            **com.packagepath.classname.methodname("params");**
            //it doesn't work, throws java.lang.ClassNotFoundException
        }
    };

    t.setContextClassLoader(cl);
    t.start();
}

notice the stared line, I wanted to use thread context classloader when I literally call a method.

I've read dozens of web pages and docs, none of them tells me certainly whether the bold line should work or not. I can't understand where went wrong.

Can literally called method use classloader to load the corresponding class? If not, why can't? I need it to work, since the calling in the jars that vendors provides are literally, not using reflection or anything else, and I have to assign different classloader for different threads to avoid name collision in the vendor jars.

Can anybody help me? Thanks a million!

Upvotes: 1

Views: 1982

Answers (1)

Tom Hawtin - tackline
Tom Hawtin - tackline

Reputation: 147164

Each class links to other classes using its own class loader. Class loaders usually delegate to their parents. You can't change the thread context class loader and expect the class to be unlinked and relinked to different classes.

So you need to make sure that the linked class is in the same class loader instance (or a parent) as the linking class.

Upvotes: 2

Related Questions