Почему мой безопасный код не работает после перехода на JDK 17

Мы создаем REST API с помощью тестов. API работает отлично, и у нас нет никаких проблем с ним. Ошибки, которые мы получаем, находятся в тестовой части.

В тестах используется библиотека Rest Assured. Мы должны использовать JDK 17 в качестве выбора уровня организации.

Мы столкнулись с проблемой при выполнении наших тестов REST Assured после обновления до JDK 17. Возможно, это как-то связано с тем, что отражение не разрешено в JDK 17.

Мы получаем java.lang.ExceptionInInitializerError для следующих строк кода

    RestAssured.baseURI = Constants.BASE_URI;

    RestAssured.port = Constants.PORT;

    RestAssured.basePath = Constants.BASE_PATH;

Есть ли у вас какие-либо советы/решения/обходные пути. Мы не можем использовать другую версию Java, поскольку это выбор на уровне организации.

Мы устанавливаем baseURI, порт и basePath для всех тестов, используя приведенный выше код. Раньше это работало, но после того, как мы перешли на JDK 17, похоже, возникла проблема.

java.lang.ExceptionInInitializerError
    at io.restassured.builder.RequestSpecBuilder.<init>(RequestSpecBuilder.java:79)
    at com.teamcenter.services.strong.utils.TestBase.createRequestSpecification(TestBase.java:99)
    at com.teamcenter.services.strong.utils.TestBase.createRequestSpecification(TestBase.java:82)
    at com.teamcenter.services.strong.utils.TestBase.setUp(TestBase.java:116)
    at com.teamcenter.services.strong.IncludeRuleTest.setUp(IncludeRuleTest.java:36)
    at junit.framework.TestCase.runBare(TestCase.java:140)
    at junit.framework.TestResult$1.protect(TestResult.java:122)
    at junit.framework.TestResult.runProtected(TestResult.java:142)
    at junit.framework.TestResult.run(TestResult.java:125)
    at junit.framework.TestCase.run(TestCase.java:130)
    at junit.framework.TestSuite.runTest(TestSuite.java:241)
    at junit.framework.TestSuite.run(TestSuite.java:236)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:90)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:93)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make java.lang.String(char[],int,int,java.lang.Void) accessible: module java.base does not "opens java.lang" to unnamed module @3cda1055
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
    at java.base/java.lang.reflect.Constructor.checkCanSetAccessible(Constructor.java:188)
    at java.base/java.lang.reflect.Constructor.setAccessible(Constructor.java:181)
    at org.codehaus.groovy.reflection.CachedConstructor$1.run(CachedConstructor.java:44)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
    at org.codehaus.groovy.reflection.CachedConstructor.<init>(CachedConstructor.java:42)
    at org.codehaus.groovy.reflection.CachedClass$2.initValue(CachedClass.java:79)
    at org.codehaus.groovy.reflection.CachedClass$2.initValue(CachedClass.java:69)
    at org.codehaus.groovy.util.LazyReference.getLocked(LazyReference.java:49)
    at org.codehaus.groovy.util.LazyReference.get(LazyReference.java:36)
    at org.codehaus.groovy.reflection.CachedClass.getConstructors(CachedClass.java:268)
    at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:218)
    at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:228)
    at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createNormalMetaClass(MetaClassRegistry.java:171)
    at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createWithCustomLookup(MetaClassRegistry.java:161)
    at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.create(MetaClassRegistry.java:144)
    at org.codehaus.groovy.reflection.ClassInfo.getMetaClassUnderLock(ClassInfo.java:253)
    at org.codehaus.groovy.reflection.ClassInfo.getMetaClass(ClassInfo.java:285)
    at org.codehaus.groovy.reflection.ClassInfo.getMetaClass(ClassInfo.java:295)
    at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.getMetaClass(MetaClassRegistryImpl.java:261)
    at org.codehaus.groovy.runtime.InvokerHelper.getMetaClass(InvokerHelper.java:873)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.createPojoSite(CallSiteArray.java:125)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallSite(CallSiteArray.java:166)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at io.restassured.internal.RequestSpecificationImpl.<clinit>(RequestSpecificationImpl.groovy:86)
    ... 19 more

Я люблю гадать.

Elliott Frisch 17.02.2023 05:35

@ElliottFrisch Это говорит о разделенных пакетах. Ошибка OP не связана с разделенными пакетами. Или я что-то упускаю?

Slaw 17.02.2023 05:48

@Slaw Мы понятия не имеем, как OP упаковывает свой код или даже какую версию проверенного OP использует; отсюда и догадки. Но модуль java.base не «открывает java.lang» для безымянного модуля, подразумевающего модули. Модули Java 9+. И эта заметка помечена как «java 9+».

Elliott Frisch 17.02.2023 06:00
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это фундаментальная проблема Groovy.

Groovy — это динамический язык, использующий Reflection для доступа к элементам и вызывающий setAccessible(true) для всех из них.

Это не должно было работать таким образом, но было реализовано таким образом, чтобы исправить доступ из закрытий к закрытым членам с побочным ущербом от игнорирования private везде. Видеть

Конструктор String(char[],int,int,java.lang.Void) даже не существует в более старых версиях Java, поэтому это не тот случай, когда старая программа полагается на него, а вместо этого среда выполнения Groovy пытается кэшировать все члены класса и вызывает setAccessible(true) заранее, как мы можем вывести из трассировки стека

    at org.codehaus.groovy.reflection.CachedClass.getConstructors(CachedClass.java:268)
    at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:218)
    at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:228)
    at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createNormalMetaClass(MetaClassRegistry.java:171)
    at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createWithCustomLookup(MetaClassRegistry.java:161)
    at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.create(MetaClassRegistry.java:144)

Обратите внимание на часть имени MetaClass, предлагающую обработку для каждого класса, и множественное число в имени метода getConstructors, предполагающее, что он пытается получить все конструкторы.

Поскольку вы даже не пытаетесь получить доступ к члену класса String в опубликованном коде, кажется, что уже достаточно использовать/сослаться на тип, чтобы вызвать инициализацию метаинформации.


Для обычного программного обеспечения Java мы бы предложили определить места, где программное обеспечение обращается к внутренним компонентам, а затем включить конкретную опцию --add-opens в качестве временного обходного пути и переписать конкретную часть, чтобы не получать доступ к внутренним компонентам в долгосрочной перспективе.

Однако для Groovy вам придется добавить такую ​​опцию для каждого пакета, который использует сценарий, без возможности переписать код, чтобы в конечном итоге избавиться от проблемы.

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

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

Спасибо. Для тех, кто посетит эту ветку в будущем, я работал со старыми версиями Groovy и Rest-Assured. Проблема решена после обновления до надежной версии 5.3.0, заводной версии 4.0.9. Очень ценю услуги сообщества stackoverflow.

Dhiraj Shetty 18.02.2023 06:22

Другие вопросы по теме