Может ли Thread.setContextClassLoader установить другой ClassLoader, отличный от возвращаемого getCCL?

Предыстория:

Недавно я реализовал фрагмент кода, который устанавливал подходящий ClassLoader для конкретной операции и, наконец, восстанавливал исходный ClassLoader после завершения операции.

Например:

ClassLoader originalCL = Thread.currentThread().getContextClassLoader();
try {
    Thread.currentThread().setContextClassLoader(specialCL);
    // do operation here that requires 'specialCL'
} finally {
    Thread.currentThread().setContextClassLoader(originalCL);
}

Согласно документу getContextClassLoader(), возвращаемый нуль может означать две вещи. 1) системный CL или 2) если получить sys CL не удалось, загрузочный CL.

возвращает контекст ClassLoader для этого потока, или значение null, указывающее загрузчик системного класса (или, в противном случае, загрузчик класса начальной загрузки)

Согласно документу setContextClassLoader(Classloader cl), если указан нулевой CL, то либо 1) системный CL, либо 2) если установка sys CL не удалась, загрузочный CL.

cl — контекст ClassLoader для этого потока, или значение null, указывающее загрузчик системного класса (или, в противном случае, загрузчик класса начальной загрузки)


Вопрос:

Возможно ли, что, используя вышеприведенную модель программирования «попробуй-наконец-восстановить», я мог бы получить другой загрузчик классов в потоке, чем я изначально?

Например:

// start out with System CL

ClassLoader original = getContextClassLoader(); // returns null

Thread.currentThread().setContextClassLoader(otherCL);

Thread.currentThread().setContextClassLoader(original); // i.e. set to null
// setCCL() tries to set System CL... fails 
// setCCL() tries to set Bootstrap CL... succeeds

Обратное также может быть верно, когда мы начинаем с Bootstrap CL, и когда мы пытаемся восстановить с помощью setContextClassLoader(null), восстанавливается System CL. Возможен ли тот или иной случай?


person Andy Guibert    schedule 18.01.2016    source источник


Ответы (1)


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

person biziclop    schedule 18.01.2016
comment
Где хранится ссылка на первоначально использованный загрузчик классов? В моих примерах я устанавливаю ClassLoader на что-то другое, а затем пытаюсь его восстановить. - person Andy Guibert; 19.01.2016
comment
@aguibert В реализации OpenJDK класс Thread просто имеет поле с именем contextClassLoader. - person biziclop; 19.01.2016
comment
часть, которую я не понимаю, заключается в том, как работает механизм аварийного переключения, когда это вступает в игру? Очевидно, что присвоить полю значение null никогда не будет ошибкой, так почему же в javadoc описывается его поведение? Если бы кто-то мог описать, почему это упоминание об отработке отказа, я бы счел это достаточным ответом. - person Andy Guibert; 19.01.2016
comment
@aguibert Я думаю, вы можете неправильно понять идиому, если это не так. Это просто означает что-то вроде «если это недоступно», а не фактический отказ чего-либо. - person biziclop; 19.01.2016