понедельник, 23 июля 2018 г.

[C++] Что такое warning C4291 и как с ним бороться

Самой яркой особенностью языка программирования C++ перед привычной мне Java является необходимость обеспечивать ручное управление памятью и на этом пути разработчика поджидает множество интересных особенностей. Например, если мы переопределяем оператор new, снабдив его нужными исключительно нам аргументами (так называемая class-specific placement allocation functions), то необходимо подобным же образом переопределить и оператор delete (имеется ввиду, что нужно определить оператор delete, имеющий сигнатуру void operator delete(void *ptr, user-defined-args...), иначе при возникновении исключительной ситуации в конструкторе класса будет не понятно какой оператор delete следует вызывать, чтобы освободить уже выделенную для создаваемого объекта данного класса память. Произойдет утечка памяти.

Предупреждение компилятора C4291


К счастью компилятор MSVC информирует разработчика об опасности, выбрасывая исключение C4291 no matching operator delete found; memory will not be freed if initialization throws an exception (код должен компилироваться с флагами компиляции /EHsc /W1). Например:

[1/2] Building CXX object src\memory\CMakeFiles\placement-new-delete.dir\PlacementNewDelete.cpp.obj
..\src\memory\PlacementNewDelete.cpp(67): warning C4291: 'void *MyClassA::operator new(size_t,MyAllocator &)': no matching operator delete found; memory will not be freed if initialization throws an exception
..\src\memory\PlacementNewDelete.cpp(32): note: see declaration of 'MyClassA::operator new'
[2/2] Linking CXX executable src\memory\placement-new-delete.exe

Подробно предупреждение компилятора C4291 описано в одноименной статье на MSDN.

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

Использование аллокатора для размещения объектов в памяти


Рассмотрим такой паттерн: использование для выделения памяти стороннего аллокатора, реализующего два метода: allocate и deallocate, каждый из которых принимает на вход параметр size_t size. Такой код довольно часто встречается в реализации JIT-компилятора в наборе компонентов для построения виртуальных машин Eclipse OMR, из чего я сделал вывод, что паттерн довольно распространен.

вторник, 17 июля 2018 г.

IBM открывает себя: WebSphere с открытым исходным кодом на JVM с открытым исходным кодом

Давно не писал заметки в блог, но есть новость и ей хочется поделиться: мой первый (и, я очень надеюсь - не последний), вклад в продукт с открытым исходным кодом Eclipse OpenJ9 был принят сообществом. Это - повод, а рассказать в данной заметке я хочу о проектах с открытым кодом, вышедших за последние годы из недр корпорации IBM. Возможно некоторые из них будут интересны вам лично или вашему бизнесу.

  • OpenLiberty - открытый сервер приложений Java EE, на базе него собирается WebSphere Liberty Profile. В качестве системы сборки используется Gradle (тесно интегрированная с bndtools, т.к. проект целиком и полностью основан на OSGi).

  • OpenJ9 - JVM с открытым исходным кодом, построенная на базе библиотеки классов из OpenJDK и другого проекта - OMR, содержащего кросс-платформенные компоненты для построения надежной и высокопроизводительной среды исполнения (т.е. на базе OMR можно построить не только JVM, но и среду исполнения для Python, Ruby или любого другого языка программирования). Какие это компоненты? Сборщик мусора, JIT-компилятор, библиотека общих кросс-платформенных функций, профайлер и т.д.

OpenJ9 и OMR открыты под эгидой сообщества Eclipse Foundation.

Теперь несколько слов о том, как собрать OpenJ9. Стоит сказать большое спасибо разработчикам за том, что они опубликовали довольно подробную инструкцию по сборке проекта с использованием вспомогательного Docker-образа и утилиты Make. Инструкция для JDK 8 может быть найдена по ссылке: Build_Instructions_V8.md, а для JDK 9 - Build_Istructions_V9.md. Обе инструкции подразумевают создание вспомогательного Docker-контейнера, содердащего компилятор C++, линковщик и все необходимые утилиты, библиотеки и заголовочные файлы. Т.е. можно не "захламлять" основное рабочее окружение если, например, разработка на C++ не является вашей основной деятельностью, а вам просто нужна свежая сборка JVM для тестов или экспериментов.

среда, 23 мая 2018 г.

Собираем свой собственный пасс компилятора под Windows как часть проекта LLVM

К сожалению под Windows отсутствует механизм динамического связывания, хотя и есть DLL, но LLVM не может зарегистрировать пользовательский пасс, оформленный как DLL, поэтому свои пассы придется собирать как часть проекта LLVM. В данной заметке я приведу небольшую инструкцию, которой очень не хватает на официальном сайте проекта.

1. Нужно скопировать каталог с исходными кодами своих пассов (буду называть его LLVMExperimentPasses) в lib/Transforms (здесь и далее пути даны относительно корня каталога с исходными кодами LLVM, предполагается, что вы уже его зачекаутили, например с GitHub-зеркала).

2. Добавить команду add_subdirectory(LLVMExperimentPasses) в файл lib/Transforms/CMakeLists.txt.

3. Для каждого созданного пасса добавить функцию с сигнатурой initialize${ИМЯ ПАССА}Pass(PassRegistry &); в заголовочный файл include/llvm/InitializePasses.h. Также следует добавить туда функцию с сигнатурой void initializeLLVMExperimentPasses(PassRegistry &);. Для пасса FunctionArgumentCount следует добавить в заголовочный файл такие строки:

// my experiment passes
void initializeLLVMExperimentPasses(PassRegistry &);
void initializeFunctionArgumentCountPass(PassRegistry &);
} // end namespace llvm
(функция обязательно должна быть определена внутри пространства имен llvm).

4. Добавить библиотеку LLVMExperimentPasses в список LLVM_LINK_COMPONENTS в файле tools/opt/CMakeLists.txt:

set(LLVM_LINK_COMPONENTS
    ${LLVM_TARGETS_TO_BUILD}
    AggressiveInstCombine
    ...
    ExperimentPasses
)
Важно: Библиотека перечисляется как ExperimentPasses, а не LLVMExperimentPasses.

5. Зарегистрировать пассы в исходном коде утилиты opt, добавив вызов функции initializeLLVMExperimentPasses в функцию main данной утилиты (в файле tools/opt/opt.cpp):

// Initialize passes
PassRegistry &Registry = *PassRegistry::getPassRegistry();
initializeCore(Registry);
...
initializeLLVMExperimentPasses(Registry);
// For codegen passes, only passes that do IR to IR transformation are
// supported.
6. Пересобрать LLVM (здесь YOUR_LLVM_BUILDTREE - каталог, в котором вы собираете вашу копию LLVM) и установить новые библиотеки и утилиты:

cd YOUR_LLVM_BUILDTREE

cmake -DCMAKE_CXX_COMPILER=YOUR_FAVOURITE_COMPILER -DCMAKE_C_COMPILER=YOUR_FAVOURITE_COMPILER -DCMAKE_LINKER=YOUR_FAVOURITE_LINKER .. -G"Ninja"

cmake --build .

cmake --build . --target install
Все, пассы готовы к использованию. Например, пасс FunctionArgumentCount из моего примера будет зарегистрирован под именем fnargcnt и может быть вызван с помощью утилиты opt:

opt.exe -fnargcnt < sum.bc > sum-out.bc

Понравилось сообщение - подпишитесь на блог

пятница, 24 ноября 2017 г.

Разворачиваем собственную среду исполнения WebSphere Liberty (с microprofile-1.2) в облаке IBM Cloud

WebSphere Liberty - это быстрый, динамичный и простой в использовании сервер приложений Java EE, основанный на проекте с открытым исходным кодом Open Liberty. Идеален для разработки, но так же и сертифицирован для промышленного использования как в IT предприятия, так и в облачном окружении.

IBM Bluemix (сейчас именуемая IBM Cloud) - это последнее облачное предложение от IBM. Облако позволяет организациям и разраотчикам быстро и просто создавать и разворачивать свои приложения в облаке. Bluemix - это реализация открытой облачной архитектуры от IBM, основанной на Cloud Foundry - Platform as a Service (PaaS) с открытым исходным кодом. IBM Cloud Foundry предлагает среды исполнения для Java, Node.JS, PHP, Python, Ruby, Swift и Go. Также доступны созданные сообществом билдпаки (build pack).

Хотя IBM Cloud уже предоставляет среду исполнения для WebSphere Liberty, иногда ее возможностей недостаточно и разработчикам требуется своя собственная версия платформы, например легковесная Liberty Kernel или старая версия для проверки обратной совместимости, или WebSphere Liberty, снабженная специфичными для разрабатываемого приложения возможностями (features).

В данной статье я хочу показать как можно развернуть вашу собственную инсталляцию WebSphere Liberty в облаке IBM Cloud, будто обычное Java-приложение. Инсталляция будет снабжена последней версией MicroProfile - открытого форума для сотрудничества над созданием микросервисов, основанных на Enterprise Java, - анонсированной 3-го октября 2017-го года.

Eclipse MicroProfile 1.2 построено на основе версии 1.1, привносит обновления для API конфигурирования приложения, а также добавляет набор новых API: проверку работоспособности (health check), устойчивость к сбоям (fault tolerance), метрики и распространение JWT. Как сказано на официальной странице проекта, цель MicroProfile - позволить сообществу развивать экосистему микросервисов на Enterprise Java в рамках коротких циклов разработки, выпуска и принятия спецификаций, некоторые из которых затем будут включены в Java JSR или другие стандарты. Сервер приложений WebSphere Liberty уже реализует данную спецификацию MicroProfile 1.2, достаточно лишь включить соответствующую возможность - microprofile-1.2 - в файл конфигурации сервера server.xml.

вторник, 14 ноября 2017 г.

Десять лет блогу Сурового челябинского программиста!


Хочу поделиться большой радостью: ровно десять лет назад в блоге Сурового челябинского программиста появилась первая, возможно с высоты приобретенного опыта ее можно оценить как несколько наивную, запись - Знакомимся: xstream - сериализуем Java-класс в XML. С тех пор, практически без перерыва (возможно за исключением последних нескольких месяцев, о чем ниже), я старался знакомить своих читателей с не сильно популярными в наших широтах технологиями такими как Eclipse Communication Framework, Java на мейнфреймах, а так же делиться опытом практического использования продуктов корпораций Oracle и IBM.

За десять лет счетчик просмотров показывает, что к страницам блога обращались 1 964 144 раз. В основном на блог заходят из поисковых систем, т.е. люди ищут и, смею надеяться, находят решения конкретных проблем. Самой популярной за все время статьей является Как подружить Hibernate со Spring и обеспечить управление транзакциями через @ннотации - 57000 просмотров, тема Open Source в принципе довольно популярна в рунете. С большим отставанием на втором месте располагается Установка и настройка MikTeX 2.7 + PsCyr с 33600 просмотрами: диплом то писать надо. Замыкает пьедестал по выражению, прозвучавшему в комментариях: "полезный пищевой концентрат", - Распределенные транзакции (XA) с помощью JTA в JavaSE (на примере Spring + Atomikos) (посчитать количество просмотров затруднительно, т.к. на статью одно время был большой паразитный траффик из Германии).

Я даже помню, как возникла идея начать вести блог. Осенью 2007-го года я, еще будучи студентом, устроился на работу Java-программистом в компанию Naumen, где разрабатывал систему управления документооборотом Naumen DMS. В университете нам Java не преподавали от слова совсем: бал правил Microsoft со своими продуктами, поэтому учиться и постигать интереснейший мир Java приходилось самостоятельно. А если некая идея, библиотека или фреймворк оказались полезными мне, то возможно они окажут помощь еще кому-нибудь. Значит нужно приобретенными знаниями и опытом поделиться. В конце-концов Интернет - он не только для котиков и "зая, я сбила крота".

Фишка выделять англоязычные слова в русском тексте курсивом родилась практически в это же время.

К сожалению, последний год писать в блог желания практически не было. Так получилось, что последние несколько лет блог был посвящен преимущественно одной теме - интеграции с использованием стека Oracle Fusion Middleware, однако корпорация Oracle с одной стороны по неизвестным мне причинам несколько раз отклонила мое резюме, а с другой - выбрала стратегию улететь в облака, что негативно сказывается на качестве продуктов сегмента on-premise. Возникает чувство, что разработка и, самое главное, поддержка данных продуктов ведется по остаточному принципу, о чем в очередной раз пришлось убедиться за последние три месяца, решая проблемы крупнейшего российского заказчика. Ну хотя бы разобрался в деталях с работой кластера серверов приложений WebLogic, выяснил, например, что безобидный код создания во время исполнения подписчика на очередь (Uniform Distributed Queue) может вызвать настоящий шторм Announcement'ов соответствующего участка JNDI-дерева остальным участникам кластера. И то хлеб. В общем, не готов сейчас сказать, буду ли продолжать вести блог, поживем - увидим.

Понравилось сообщение - подпишитесь на блог

пятница, 9 июня 2017 г.

Валидация DVM после обновления потребляет весь CPU, или как мы заставили Oracle выпустить patch

Постановка задачи


Пришли как-то к Суровому коллеги с интересным вопросом. Суть в следующем: каждый раз после обновления MDS производительность промышленного контура одной немаленькой системы, написанной на Oracle SOA Suite, критически падает, при этом загрузка центральных процессоров серверов, на которых развернута система, очень сильно возрастает.

Особенностью системы является активное использование такого механизма Oracle SOA Suite как Domain Value Maps (DVM), предназначенного для перекодировки значений из ограниченного набора одной предметной области (при интеграции - одной информационной системы) в значения, характерные для другой предметной области (информационной системы). Например наши любимые российские рубли в одной системе могут кодироваться как RUR, а в другой - 810. Механизм DVM удобен для работы со справочниками конвертации, которые изменяются нечасто, однако, если все же справочник требуется изменить, то в состав Oracle SOA Suite входит инструмент с развитым веб-интерфейсом - SOA Composer, - позволяющий сделать это бизнес-пользователю без привлечения разработчиков.

Как оказалось, все работает идеально пока такие справочники небольшие, однако если их размер увеличивается до сотен килобайт, то пользователей и администраторов Oracle SOA Suite ждут сюрпризы.

Посмотрим на дамп потоков, собранный во время, когда наблюдалась проблема.

"[ACTIVE] ExecuteThread: '57' for queue: 'weblogic.kernel.Default (self-tuning)'" #159 daemon prio=9 os_prio=2 tid=0x0000000066bbd800 nid=0x28ac runnable [0x0000000079188000]
java.lang.Thread.State: RUNNABLE
at oracle.xml.xpath.XPathChildAxis.getNodeList(XPathAxis.java:600)
at oracle.xml.xpath.XPathStep.evaluate(XPathStep.java:1102)
at oracle.xml.xpath.PathExpr.evaluate(PathExpr.java:808)
at oracle.xml.xpath.ComparisonExpr.evaluate(XSLExpr.java:1743)
at oracle.xml.xpath.XSLExprBase.testBooleanExpr(XSLExprBase.java:514)
at oracle.xml.xpath.AndExpr.evaluate(XSLExpr.java:524)
at oracle.xml.xpath.XSLExprBase.testBooleanExpr(XSLExprBase.java:514)
at oracle.xml.xpath.AndExpr.evaluate(XSLExpr.java:524)
at oracle.xml.xpath.XSLExprBase.testBooleanExpr(XSLExprBase.java:514)
at oracle.xml.xpath.AndExpr.evaluate(XSLExpr.java:524)
at oracle.xml.xpath.XPathPredicate.filter(XPathPredicate.java:349)
at oracle.xml.xpath.XPathChildAxis.getNodeList(XPathAxis.java:627)
at oracle.xml.xpath.XPathStep.evaluate(XPathStep.java:1102)
at oracle.xml.xpath.PathExpr.evaluate(PathExpr.java:808)
at oracle.xml.parser.v2.XMLNode.selectNodes(XMLNode.java:2762)
at oracle.xml.parser.v2.XMLNode.selectNodes(XMLNode.java:2722)
at oracle.tip.dvm.sdk.util.XMLUtil.isDVMDocumentValid(XMLUtil.java:211)
at oracle.tip.dvm.entity.DVMRTObject.validateDVM(DVMRTObject.java:202)
at oracle.tip.dvm.entity.DVMRTObject.(DVMRTObject.java:130)
at oracle.tip.dvm.DVMManagerImpl.getDVMRTObject(DVMManagerImpl.java:217)
at oracle.tip.dvm.DVMManagerImpl.lookupValue(DVMManagerImpl.java:133)
at oracle.tip.dvm.LookupValue.lookupValue(LookupValue.java:95)
at oracle.tip.dvm.LookupValue.lookupValue(LookupValue.java:252)
at sun.reflect.GeneratedMethodAccessor1815.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at oracle.xml.xpath.XSLExtFunctions.callStaticMethod(XSLExtFunctions.java:115)
at oracle.xml.xpath.XPathExtFunction.evaluateMethod(XPathExtFunction.java:422)
at oracle.xml.xpath.XPathExtFunction.evaluate(XPathExtFunction.java:347)
at oracle.xml.xslt.XSLValueOf.processAction(XSLValueOf.java:152)
at oracle.xml.xslt.XSLNode.processChildren(XSLNode.java:559)
at oracle.xml.xslt.XSLTemplate.processAction(XSLTemplate.java:278)
at oracle.xml.xslt.XSLStylesheet.execute(XSLStylesheet.java:706)
at oracle.xml.xslt.XSLStylesheet.execute(XSLStylesheet.java:665)
at oracle.xml.xslt.XSLProcessor.processXSL(XSLProcessor.java:401)
at oracle.xml.jaxp.JXTransformer.transform(JXTransformer.java:578)
at ...

среда, 31 мая 2017 г.

Безопасность транзакций между доменами Oracle WebLogic Server

Управляя распределенной (XA) транзакцией, менеджер транзакций должен иметь возможность связываться со всеми участниками транзакции. Т.е. со всеми серверами и ресурсами в ней участвующими. Коммуникационные каналы настраиваются в зависимости от того, куда направляется транзакция:

  • Inter-domain - коммуникация между серверами, участвующими в транзакции и расположенными не в одном и том же домене

  • Intra-domain - коммуникация между серверами, участвующими в транзакции и расположенными в одном и том же домене.

Каналы коммуникации для транзакций должны быть защищенными, чтобы предотвращать от атак вида человек посредине. Сервер приложений Oracle WebLogic предоставляет следующие опции для защиты коммуникационных каналов:

  • Cross Domain Security - используется отображение учетных данных пользователей для настройки совместимого коммуникационного канала между серверами в транзакциях между доменами. Хотя это требует более сложной конфигурации, Cross Domain Security позволяет настроить доверие между отдельными доменами.

  • Security Interoperability Mode - устанавливает доверие между всеми доменами, которые участвуют в транзакции, путем
    установки для учетных данных всех доменов (domain credentials) совпадающих значений, т.е. principal из одного домена разрешен и в других. Этот режим проще для настройки чем Cross Domain Security, однако некоторые настройки Security Interoperability Mode полагаются на доверие домена и менее безопасны.

Рассмотрим преимущества и недостатки данных режимов.