Почему Java не может использовать загрузчик классов контекста потока, когда метод вызывается буквально? - PullRequest
1 голос
/ 01 марта 2010

Я написал собственный загрузчик классов 'JarClassLoader', который сам по себе работает нормально, так как следующий тестовый пример зеленый:

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

Но следующий тест не будет работать:

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();
}

обратите внимание на размеченную строку, я хотел использовать потоковый загрузчик классов, когда я буквально вызываю метод.

Я прочитал десятки веб-страниц и документов, и ни один из них не сказал мне точно, должна ли жирная линия работать или нет. Я не могу понять, где что-то пошло не так.

Может ли буквально вызываемый метод использовать classloader для загрузки соответствующего класса? Если нет, то почему не можете? Мне нужно, чтобы это работало, поскольку вызовы в jar-файлах, предоставляемых поставщиками, в буквальном смысле слова не используют отражение или что-либо еще, и мне приходится назначать разные загрузчики классов для разных потоков, чтобы избежать конфликта имен в jar-файлах поставщика.

Кто-нибудь может мне помочь? Спасибо миллион!

1 Ответ

2 голосов
/ 01 марта 2010

Каждый класс связывается с другими классами, используя свой собственный загрузчик классов. Загрузчики классов обычно делегируют своим родителям. Вы не можете изменить загрузчик класса контекста потока и ожидать, что класс будет не связан и не связан с другими классами.

Таким образом, вы должны убедиться, что связанный класс находится в том же экземпляре загрузчика классов (или родительском), что и класс связывания.

...