В Java классы загружаются в память специальными объектами — класс-лоадерами (class loaders). Каждый класс-лоадер формирует своё собственное пространство видимости классов.
Виды класс-лоадеров:
$JAVA_HOME/lib/ext.Особенности:
Можно ли загрузить несколько версий одного и того же класса в процесс JVM, и как это сделать?
Ответ: Да, возможно, если использовать разные class loaders. Классы с одинаковым FQDN, загруженные разными загрузчиками, считаются разными типами для JVM.
Пример:
ClassLoader loader1 = new URLClassLoader(new URL[]{...}); ClassLoader loader2 = new URLClassLoader(new URL[]{...}); Class clazz1 = loader1.loadClass("com.example.MyClass"); Class clazz2 = loader2.loadClass("com.example.MyClass"); System.out.println(clazz1 == clazz2); // false
История
В крупной серверной системе использовали плагины, каждый из которых подключался через отдельный custom classloader. Плагины обменивались объектами через общий интерфейс, также загруженный своим classloader'ом. Возникало ClassCastException при приведении типов, так как interface 'PluginApi' из classloader плагина и основной системы считался разными типами.
История
Попытка "горячей" перезагрузки сервлета через custom classloader привела к утечкам памяти — старый класс из памяти не выгружался, поскольку в статических переменных где-то оставалась ссылка. В результате PermGen быстро переполнялся.
История
Продукт с поддержкой динамической загрузки модулей неявно использовал системный class loader, а разработчики случайно подменили его родителя, потеряв доступ к базовым классам (например, из JDK). Это проявилось в падениях, когда новый модуль не мог загрузить стандартные Java-классы, например,
java.sql.Driver.