При разработке мобильных решений на платформе 1С, требующих высокого уровня безопасности, часто возникает необходимость использовать клиентские сертификаты для авторизации устройства на сервере. Однако многие разработчики сталкивались с тем, что приложение начинает «вылетать» при выполнении серии запросов. Давайте разберем, почему это происходит и как устранить данную проблему.
Ситуация, которую мы рассматриваем, заключается в следующем: при создании защищенного соединения через ЗащищенноеСоединениеOpenSSL с использованием объекта СертификатКлиентаФайл, приложение стабильно работает при выполнении одиночных запросов. Но стоит нам запустить цикл, в котором эти объекты инициализируются повторно, как через несколько итераций приложение аварийно завершается.
Исследование с помощью анализа логов (LogCat) показывает, что причиной является JNI ERROR (app bug): global reference table overflow. Простыми словами, мобильная платформа 1С при каждом создании ЗащищенноеСоединениеOpenSSL с клиентским сертификатом некорректно освобождает ресурсы на стороне виртуальной машины Android (ART/Dalvik). В результате таблица глобальных ссылок JNI переполняется, что неизбежно ведет к принудительному закрытию (крашу) приложения.
Самое важное, что стоит сделать — проверить версию вашей мобильной платформы. Проблема была официально признана разработчиками фирмы «1С» как дефект платформы (зарегистрирован под кодом 10231179). Данная ошибка была успешно исправлена в версии мобильной платформы 8.3.19.51 и во всех последующих релизах. Поэтому, если у вас есть возможность, обязательно обновите платформу до актуального релиза.
Если обновление платформы по какой-то причине временно невозможно, необходимо пересмотреть логику работы с сетевыми соединениями, чтобы минимизировать нагрузку на память и избежать утечек ресурсов. Рассмотрим, как правильно организовать код.
Главное правило: не инициализируйте тяжелые объекты внутри циклов. Вместо этого используйте кэширование.
Рассмотрим наглядный пример того, как делать не нужно:
// ОПАСНЫЙ КОД, ПРИВОДЯЩИЙ К КРАШУ
Для Ном = 1 По 100 Цикл
СертификатКлиента = Новый СертификатКлиентаФайл(ИмяФайла, Пароль);
SSL = Новый ЗащищенноеСоединениеOpenSSL(СертификатКлиента, Новый СертификатыУдостоверяющихЦентровОС);
HTTPСоединение = Новый HTTPСоединение(АдресСервера,,,,,20, SSL);
Ответ = HTTPСоединение.Получить(Новый HTTPЗапрос(Запрос));
КонецЦикла;
В этом примере при каждой итерации создаются новые объекты, которые платформа не успевает корректно выгрузить из оперативной памяти Android. Чтобы избежать переполнения, перенесем инициализацию объектов в кэш. Для этого удобно использовать модуль с повторным использованием возвращаемых значений.
Правильный подход выглядит так:
// ПРАВИЛЬНЫЙ ПОДХОД
// В модуле с повторным использованием
Функция ПолучитьСертификат(ИмяФайла, Пароль) Экспорт
Возврат Новый СертификатКлиентаФайл(ИмяФайла, Пароль);
КонецФункции
// В основном коде
Сертификат = МодульПовтИсп.ПолучитьСертификат(ИмяФайла, Пароль);
SSL = Новый ЗащищенноеСоединениеOpenSSL(Сертификат, Новый СертификатыУдостоверяющихЦентровОС);
Для Ном = 1 По 100 Цикл
// Переиспользуем объект соединения или создаем его минимальное количество раз
HTTPСоединение = Новый HTTPСоединение(АдресСервера,,,,,20, SSL);
Ответ = HTTPСоединение.Получить(Новый HTTPЗапрос(Запрос));
КонецЦикла;
СертификатКлиентаФайл и ЗащищенноеСоединениеOpenSSL один раз на сеанс работы приложения, если это позволяют условия безопасности.ПовторноеИспользованиеВозвращаемыхЗначений = Истина.HTTPСоединение внутри циклов, если можно обойтись одним экземпляром на всю операцию.LogCat — это поможет понять, не исчерпали ли вы лимиты операционной системы.Подводя итог: проблема краша мобильной платформы при работе с SSL-сертификатами в большинстве случаев решается обновлением до версии 8.3.19.51 и выше. В остальных ситуациях строгое соблюдение принципов кэширования объектов и оптимизация вызовов сетевых соединений помогут вам добиться стабильной работы приложения на мобильных устройствах.