скопировано отсюда
ил очень специфическую проблему, решение которой кажется чем-то базовым:
Иерархия загрузчика классов моего (Spring) приложения выглядит примерно так:SystemClassLoader -> PlatformClassLoader -> AppClassLoader
Если я использую JavaCompleteableFuture
запускать темы.ContextClassLoader
из потоков это:SystemClassLoader -> PlatformClassLoader -> ThreadClassLoader
Таким образом, я не могу получить доступ к любому классу вAppClassLoader
хотя я должен, потому что все внешние классы библиотеки находятся там.
Исходная база довольно большая, поэтому я не хочу / не могу переписать все части, связанные с потоками, во что-то другое (например, передавать пользовательский исполнитель для каждого вызова).
Итак, мой вопрос:Как я могу создать темы, созданные, например,CompleteableFuture.supplyAsync()
использоватьAppClassLoader
как родитель? (вместоPlatformClassloader
)
я узнал чтоForkJoinPool используется для создания тем. Но, как мне кажется, там все естьстатический а такжеокончательный, Поэтому я сомневаюсь, что даже установив кастомForkJoinWorkerThreadFactory в этом случае поможет системное свойство. Или это будет?
Изменить, чтобы ответить на вопросы из комментариев:
где вы развертываете? Это работает в пределах Jetty / Tomcat / любого контейнера JEE?
Я использую настройку Spring Boot по умолчанию, поэтому используется внутренний контейнер Tomcat.Какая именно у вас проблема?
Точная проблема:java.lang.IllegalArgumentException: org.keycloak.admin.client.resource.RealmsResource, на который ссылается метод, не отображается в загрузчике классовЗадания, которые вы отправляете в supplyAsync (), создаются из AppClassLoader, не так ли?
supplyAsync
называется изMainThread
который используетAppClassLoader
, Но отладка приложений показывает, что все такие потоки имеютPlatformClassLoader
как их родитель. Что касается моего понимания, это происходит потому, чтоForkJoinPool.commonPool () создается во время запуска приложения (потому что он статический) и поэтому использует загрузчик класса по умолчанию в качестве родителя, которыйPlatformClassLoader
, Итак, все потоки из этого пула получаютPlatformClassLoader
как их родитель дляContextClassLoader (вместоAppClassLoader
).
Когда я создаю своего собственного исполнителя внутриMainThread
и передать этого исполнителяsupplyAsync
все работает - и я вижу во время отладки, что действительно сейчасAppClassLoader
родитель моегоThreadClassLoader
, Который, кажется, подтверждает мое предположение в первом случае, что общий пул не создаетсяMainThread
по крайней мере, когда он используетAppClassLoader
сам.
Полная трассировка стека:
java.lang.IllegalArgumentException: org.keycloak.admin.client.resource.RealmsResource referenced from a method is not visible from class loader
at java.base/java.lang.reflect.Proxy$ProxyBuilder.ensureVisible(Proxy.java:851) ~[na:na]
at java.base/java.lang.reflect.Proxy$ProxyBuilder.validateProxyInterfaces(Proxy.java:682) ~[na:na]
at java.base/java.lang.reflect.Proxy$ProxyBuilder.<init>(Proxy.java:628) ~[na:na]
at java.base/java.lang.reflect.Proxy.lambda$getProxyConstructor$1(Proxy.java:426) ~[na:na]
at java.base/jdk.internal.loader.AbstractClassLoaderValue$Memoizer.get(AbstractClassLoaderValue.java:327) ~[na:na]
at java.base/jdk.internal.loader.AbstractClassLoaderValue.computeIfAbsent(AbstractClassLoaderValue.java:203) ~[na:na]
at java.base/java.lang.reflect.Proxy.getProxyConstructor(Proxy.java:424) ~[na:na]
at java.base/java.lang.reflect.Proxy.newProxyInstance(Proxy.java:999) ~[na:na]
at org.jboss.resteasy.client.jaxrs.ProxyBuilder.proxy(ProxyBuilder.java:79) ~[resteasy-client-3.1.4.Final.jar!/:3.1.4.Final]
at org.jboss.resteasy.client.jaxrs.ProxyBuilder.build(ProxyBuilder.java:131) ~[resteasy-client-3.1.4.Final.jar!/:3.1.4.Final]
at org.jboss.resteasy.client.jaxrs.internal.ClientWebTarget.proxy(ClientWebTarget.java:93) ~[resteasy-client-3.1.4.Final.jar!/:3.1.4.Final]
at org.keycloak.admin.client.Keycloak.realms(Keycloak.java:114) ~[keycloak-admin-client-3.4.3.Final.jar!/:3.4.3.Final]
at org.keycloak.admin.client.Keycloak.realm(Keycloak.java:118) ~[keycloak-admin-client-3.4.3.Final.jar!/:3.4.3.Final]