Избранные Материалы

Java :: classpath менеджмент во время выполнения

Постановка задачи

Необходимо дать возможность модифицировать classpath во время выполнения приложения. Это может понадобиться при разработке механизма управления аддонами (расширениями) приложения, в случае, когда JAR-файлы содержашие соответствующие классы нужно добавить в classpath в зависимости от конкретной конфигурации приложения либо еще каких-то условий, зависящих от бизнес-логики.

Решение

При помощи метода ClassLoader.getSystemClassLoader() можно получить системный загрузчик классов - екземпляр класса java.net.URLClassLoader. Он имеет метод addURL(java.net.URL), который, собственно, и определяет URLs которые будут использованы при необходимости загрузки того или иного класса во время выполнения приложения.

Небольшой нюанс лишь в том, что этот метод имеет спецификатор доступа protected, а значит вызвать его напрямую не получится.

На помощь приходит механизм отражения Java. Перед вызовом метода, нужно лишь сделать его доступным для вызова “извне” при помощи другого метода - setAccessible(boolean) класса java.lang.reflect.Method.

Код

Ниже следует пример кода, который добавляет к classpath’у URLs всех файлов внутри заданной директории с аддонами. В реальной ситуации, естественно, бизнес-логика этого процесса может быть значительно более комплексной.

package examples;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

/**
 * @author kion
 *
 * Пример класса, модифицирующего classpath прямо во время выполнения.
 *
 */
public class AddOnsLoader {

    // директория, содержащая аддоны
    private static final File ADDONS_DIR = new File("/path/to/dir/with/addons");

    // префикс для URL локальных файлов
    private static final String FILE_PROTOCOL_PREFIX = "file:";

    public static void loadAddOns() throws Throwable {
        // проверка существования директории с аддонами
        if (ADDONS_DIR.isDirectory()) {
            for (File file : ADDONS_DIR.listFiles()) {
                // добавление каждого из найденых файлов к classpath
                addClassPathURL(FILE_PROTOCOL_PREFIX + file.getAbsolutePath());
            }
        }
    }

    private static void addClassPathURL(String path) throws Throwable {
        // URL файла для добавления к classpath
        URL u = new URL(path);
        // достаем системный загрузчик классов
        URLClassLoader urlClassLoader =
            (URLClassLoader) ClassLoader.getSystemClassLoader();
        // используя механизм отражения,
        // достаем метод для добавления URL к classpath
        Class urlClass = URLClassLoader.class;
        Method method = urlClass.getDeclaredMethod(
                "addURL",
                new Class[]{ URL.class });
        // делаем метод доступным для вызова
        method.setAccessible(true);
        // вызываем метод системного загрузчика,
        // передавая в качестве параметра
        // URL файла для добавления к classpath
        method.invoke(urlClassLoader, new Object[]{ u });
    }

}

(голосов: 2, рейтинг: 5 из 5)
Войдите, чтобы поставить оценку.

Один комментарий »

Войдите, чтобы оставить комментарий

  • Bloggeram