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

14002

iOS :: Hack — полноценный доступ к файловой системе внешнего накопителя

iOS :: Hack — полноценный доступ к файловой системе внешнего накопителя

15215

Bias :: Многофункциональный информационный менеджер

Bias :: Многофункциональный информационный менеджер

13023

Релиз Ext GWT (GXT) 2.0

Релиз Ext GWT (GXT) 2.0

26947

Светлое будущее Java

Светлое будущее Java

7238

Фриланс :: Стоит ли?

Фриланс :: Стоит ли?

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

}
Tweet

Об авторе:
Профессиональный разработчик программного обеспечения, блоггер, адепт Open Source, казуальный путешественник, фотограф-аматор.
Подробнее »
Комментировать Послать ссылку на эту статью по e-mail