Подтвердить что ты не робот

Что люди используют для загрузки классов?

Итак, каждый текстовый учебник Java рассказывает о том, насколько гибкой является Java, поскольку он может загружать классы во время выполнения. Просто соберите строку и передайте ее Class.forName(), и поймайте ClassNotFoundException и обработайте ее. Так много для теории.

Можете ли вы привести примеры того, как вы использовали загрузку классов Java для достижения функции, которая в противном случае была бы невозможной или простой? Обратите внимание, что я not спрашиваю: "Какие великие вещи могли делать?" - Я ищу примеры в реальном мире, будь то приложение с открытым исходным кодом или - если вы можете описать это, не выдавая слишком много деталей, - это проприетарное приложение.

Изменить: Разумеется, VM загружает классы лениво, когда они им нужны. Это закулисная вещь, пока я уверен, что все классы, которые мне когда-либо понадобится, есть. Как обращаться с ClassNotFoundException? Предположим, что я написал десять страниц с текстом, а класс PrinterDriver не найден.

4b9b3361

Ответ 1

Плагины - это первое, что приходит на ум. Загрузка класса Java делает его очень легким по сравнению с такими языками, как С++.

Один момент, о котором вы, возможно, и не подозреваете, - это то, что любая виртуальная машина Java в значительной степени полагается на загрузку класса внутри. Каждый раз, когда ссылка на, скажем, метод просматривается интерпретатором байт-кода, он проверяет, уже ли загружен класс, к которому относится этот метод, а если нет, загружает его, используя тот же механизм за Class.forName() до разрешения метода, Этот mecanism очень мощный, поскольку любое приложение Java действительно действует как набор сменных компонентов, которые все динамически загружаются. Если VM хорошо написана, она может, например, загружать классы через пользовательский загрузчик классов, который извлекает классы из сети вместо обычных файлов.

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

Ответ 2

"PLUGIN", и это большое слово.

В принципе, вы можете загрузить класс, который вы не знаете, когда или не существует, когда вы пишете и компилируете свою программу.

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

Драйвер DB, плагин Eclipse, язык Script, все методы шифрования выполняются по мере того, как оригинальный автор не знает (и в некоторых случаях не имеет понятия), какой класс действительно будет использоваться.

Надеюсь, что это поможет.

Ответ 3

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

  • вы можете развернуть одно и то же веб-приложение дважды по другому пути.
  • два приложения могут зависеть от двух разных версий одной и той же библиотеки без конфликтов.

Благодаря волшебству классных загрузчиков...

Ответ 4

Ну, я использовал его для динамической загрузки драйверов JDBC в приложение J2EE. Это могло быть сделано лучше, я понятия не имею.

В то время было просто сделать вызов forName().

Ответ 5

Я уверен, что загрузка плагина в Java сильно зависит от этого.

Приложение проверяет именованные функции и выполняет их

Eclipse фактически использует это для плагинов

Основная идея - выполнить код, который не был запланирован во время разработки.

Ответ 6

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

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

Ответ 7

КлассLoader также используется для ресурсов неклассов. На память приходят файлы конфигурации. Поскольку существует четко определенный порядок поиска, легко вставить собственные "log4j.xml" или "hibernate.properties", и приложение найдет и использует его.

Ответ 8

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

А также путем настройки загрузчика классов вы можете преобразовывать классы по мере их загрузки. Это используется некоторыми структурами ORM, а также некоторыми структурами AOP.

Ответ 9

JDBC API - отличный пример для этого. Таким образом, вы можете настроить драйвер JDBC извне, например, в файл свойств:

driver = com.dbvendor.jdbc.Driver
url = jdbc:dbvendor://localhost/dbname
username = stackoverflow
password = youneverguess

.. который вы можете использовать как:

Properties properties = new Properties();
properties.load(Thread.currentThread().getResourceAsStream("jdbc.properties"));

String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");

Class.forName(driver);
Connection connection = DriverManager.getConnection(url, username, password);

Каждая реализация драйвера JDBC в основном регистрируется в DriverManager внутри блока инициализатора static. Это именно тот, который выполняется во время Class#forName().

package com.dbvendor.jdbc;

public class Driver implements java.sql.Driver {

    static {
         java.sql.DriverManager.registerDriver(new Driver());
    }

    private Driver() {
        // ...
    }

    public boolean acceptsURL(String url) {
        return url.startsWith("jdbc:dbvendor");
    }

}

Так как DriverManager примерно выглядит так (на самом деле он использует старомодный Vector)

private static final Set<Driver> drivers = new HashSet<Driver>();

public static void registerDriver(Driver driver) {
    drivers.add(driver);
}

public static Connection getConnection(String url, String username, String password) throws SQLException {
    for (Driver driver : drivers) {
        if (driver.acceptsURL(url)) {
            return driver.connect(url, username, password);
        }
    }
    throw new SQLException("No suitable driver");
}

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

Таким образом, JDBC-код очень портативен. Вы можете изменить БД или распространять код среди пользователей с другой БД без необходимости изменения/взлома/восстановления самого кода.

Это не только JDBC, который использует этот подход, но и другие API, такие как API сервлета, ORM, такие как Hibernate/JPA, фреймворки зависимостей, и т.д. использует отражение для загрузки классов на основе внешне настраиваемых свойств файлов, файлов конфигурации XML и/или аннотаций, Все это делает код намного более портативным и подключаемым.

Ответ 10

Я думаю, что JUnit может также использовать множество функций отражения, чтобы сделать общий шаблон теста.

Ответ 11

Механизм загрузчика классов Java является мощным, поскольку он обеспечивает точку абстракции точно в том месте, где загружается код, что позволяет делать такие вещи, как:

  • нахождение битов класса в некотором месте, отличном от пути к классам (db, удаленный url, файловая система и т.д.)
  • Загрузка исходного кода, который вы только что создали и скомпилировали (с помощью javac api)
  • Загруженный байт-код, который вы только что создали (скажем, с ASM)
  • загружать код и ИЗМЕНИТЬ его перед его использованием (с ASM, агентами Java и т.д.)
  • Код RE-Load на лету
  • цепные погрузчики вместе в деревьях (обычное делегирование) или веб-сайтах (стиль OSGi на основе родного языка) или все, что вы хотите

В момент изменения кода во время загрузки есть целый мир интересных вещей, которые вы можете сделать, чтобы пересоздать свой код - AOP, профилирование, отслеживание, модификации поведения и т.д. В Terracotta мы полагались на абстракцию загрузчика классов, чтобы динамически загружать класс, затем перехватите весь доступ к полям и динамически добавьте возможность загрузки состояния из того же объекта на удаленном node в кластере позже. Прохладный материал.

Ответ 12

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

Ответ 13

См. поддержку Oracle Обработка LOB в Spring Framework, например. Только потому, что структура предлагает определенную поддержку Oracle, вы, вероятно, не хотите развертывать источник данных Oracle как зависимость для вашего, например. Проекты MySQL. Поэтому вы грубо загружаете драйверы Oracle в область экземпляра обработчика LOB.

Ответ 14

Контейнеры сервлетов, такие как Tomcat, читают ваш файл конфигурации war/webapp из WEB-INF/web.xml и загружают ваш сервлет/фильтр/и т.д. подклассы на основе значений String, которые вы помещаете в файл XML. Для соединений с базой данных они вытягивают имя класса для загрузки из вашей конфигурации, например. "com.mysql.jdbc.Driver" для MySQL.

Ответ 15

Пример реального мира (по вашему запросу), проприетарное приложение (как это явно разрешено вашим вопросом)...

При запуске клиентское программное обеспечение связывается с нашим сервером (серверами) и говорит: "Реализация интерфейса интерфейса по умолчанию у меня есть Foo (потому что на самом деле каждая версия 1.03, например, использует Foo), у вас есть лучший?" Если между тем мы написали лучшую реализацию, мы ответим "yup, Bar стар, используйте Buz, это лучше".

Затем на стороне клиента загрузчик классов используется для загрузки последней версии.

Это упрощение, но это пример реального мира. Это не совсем не похоже на пример JRL: где устаревшие классы автоматически заменяются более новыми.

Ответ 16

Использование загрузки динамического класса также очень полезно для загрузки файлов конфигурации в качестве упоминаний Тило. В более общем плане динамическая загрузка классов может обеспечить хороший уровень абстракции файловой системы во многих ситуациях, упрощая настройку записи и настраиваемый код. Просто убедитесь, что ресурс, который вам нужен, находится в пути к классам и загружает его как InputStream.

Кроме того, с помощью специального обработчика протокола в Java можно получить доступ к элементам в пути к классам через URL. Это не является преимуществом, характерным для загрузки динамического класса, но оно демонстрирует, как доступ к ресурсам класса path можно получить через тот же API, что и другие ресурсы (даже удаленные). http://java.sun.com/developer/onlineTraining/protocolhandlers/

Ответ 17

Любая структура, основанная на конфигурации (struts, jsf, spring, hibernate и т.д.), использует этот механизм. Любой продукт, основанный на архитектуре плагина, также использует эту функцию.

Ответ 18

Вы можете использовать метод Class:: forName, если класс находится в пути к классу. Однако, если вам нужно указать путь вместе с именем класса i.e c:\document\xyz.class, вам придется использовать класс URLClassLoader.