Как загрузить java.util.TimeZone более одного раза в JVM - PullRequest
2 голосов
/ 27 июня 2019

Я создаю свой пользовательский загрузчик классов:

new URLClassLoader(urls, Thread.currentThread().getContextClassLoader());

, где urls - это new Url("java.util.TimeZone")

После этого я загружаю класс по имени:

Class<?> newTimeZoneClass = loader.loadClass("java.util.TimeZone");

иnewTimeZoneClass==TimeZone.class возвращает true.

Основная причина того, что мой загрузчик классов загружает класс из родительского загрузчика.Как это исправить?

Ответы [ 2 ]

1 голос
/ 27 июня 2019

Вы не можете сделать это. Модель безопасности Java запрещает любому загрузчику классов создавать класс в иерархии «java. *». Это жестко закодировано в собственном коде JVM, поэтому обходного пути нет.

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

В любом случае, есть несколько способов сделать это.

Во-первых, TimeZone является абстрактным классом, и фактическая реализация обычно sun.util.calendar.ZoneInfo. Так как этого нет в иерархии java. *, Вы можете создать несколько копий в ваших загрузчиках классов.

Во-вторых, вы можете создать подкласс TimeZone и делегировать все методы экземпляру, предоставленному JVM, добавив при этом свою собственную функциональность. Я использовал это для создания экземпляров TimeZone в некоторых моих приложениях.

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

Если вы хотите изменить TimeZone экземпляры, возвращаемые статическими методами в TimeZone, они делегируются на ZoneInfo, и вам придется использовать отражение, чтобы изменить результат. Если вы знаете Aspect-J или его эквивалент, вы также можете перехватить вызов.

1 голос
/ 27 июня 2019

Как упомянуто в Java Doc public URLClassLoader(URL[] urls, ClassLoader parent):

Создает новый URLClassLoader для данных URL.URL-адреса будут искать в порядке, указанном для классов и ресурсов, после первого поиска в указанном родительском загрузчике классов.

Я предполагаю, что вы должны создать CustomClassLoader ccl = new CustomClassLoader(); или использовать другой конструктор, передав объект AccessControlContext - URLClassLoader(URL[] urls, ClassLoader parent, AccessControlContext acc) или URLClassLoader(URL[] urls, AccessControlContext acc).

Есть несколько статей по созданию нового классапогрузчики:

https://www.baeldung.com/java-classloaders

https://www.javaworld.com/article/2077260/learn-java-the-basics-of-java-

https://www.oodlestechnologies.com/blogs/Creating-Custom-Class-Loader-In-JAVA/class-loaders.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...