Содержание

  1. 1с-ка не видит Java (для запуска оптимизированной реструктуризации)
  2. Как ускорить процесс реструктуризации и обновления 1С в разы
  3. Умение находить и устранять причины медленной и нестабильной работы систем на 1С обязательно для программистов 1С
  4. После курса Вы сможете:
  5. Для кого этот курс
  6. Комментарии / обсуждение (48):
  7. 1с критическая ошибка работы java процесса
  8. Версия механизма реструктуризации
  9. Параллелизм СУБД в процессе реструктуризации
  10. Как получать полное описание ошибки при работе оптимизированного механизма реструктуризации (v2)
  11. По каким причинам может не работать второй механизм реструктуризации

Платформа 8.3.15.1830. Конфигурация в режиме совместимости 8.3.14. На кластере установлена Java 8. 1С и Java 64-бит.
Путь к джаве прописан в conf.cfg: JavaHome=C:Program FilesJavajre1.8.0_261
Путь к джаве прописан в переменных среды

Запускаю реструктуризацию, через несколько минут ошибка:

В процессе обновления конфигурации базы данных при работе оптимизированного механизма обновления произошла критическая ошибка
по причине:
Не определен путь до каталога установки Java.

Сервер перезагружал, параметр удалял/добавлял в conf.cfg — без разницы
Не совсем понимаю, что мешает 1с-ке.

С ИТС про JavaHome в conf.cfg:

Определяет путь к директории установки JAVA. В случае если данный параметр не задан, то путь до директории установки JAVA определяется в переменной окружения JAVA_HOME. Используется в конфигурационном файле на компьютере, где расположен кластер серверов «1С:Предприятия».

Для ОС Windows в случае, есть в файле conf.cfg данный параметр не задан и не установлена переменная JAVA_HOME, то путь до директории установки JAVA будет определен из системного реестра, куда информация заносится при установке JRE.
—-

Т.е в принципе 1Ска должна найти Джаву по реестру после установки, без дополнительного прописывания в файле и переменных. Пробовал и до bin’а прописывать, хотя вроде достаточно C:Program FilesJavajre1.8.0_261.

До этого конфигуратор запускал на самом сервере(где 1Ска и Java) — ошибка. Сейчас запустил конфигуратор с локальной машины и он крутится уже достаточно долго. я правда не уверен что включился режим оптимизированной реструктуризации, не очень понятно как это можно проверить

Источник

Как ускорить процесс реструктуризации и обновления 1С в разы

Нам всем знакомо, как долго может идти обновление: это может занимать несколько часов, а в некоторых случаях – даже
несколько дней.

Однако, его можно заметно ускорить. А для этого нужно немного погрузиться в детали и поговорить о реструктуризации 🙂

Когда в 1С изменяются метаданные (добавляются документы, реквизиты, индексы), происходит изменение структуры таблиц.

При запуске обновления создается полная копия таблицы, включая индексы – уже с новой структурой. Этот процесс называется реструктуризацией. Разумеется, это все занимает довольно заметное время.

Для случаев, когда объемы данных небольшие, это не так чувствительно.

Но реструктуризация больших баз, в которых содержатся таблицы с десятками миллионов строк, может затянуться на несколько часов или даже дней. Потеря такого количества времени – это уже весьма болезненно.

Еще в платформе 8.3.11 появился механизм, который помогает ускорить реструктуризацию в разы, а в некоторых случаях – на порядки.

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

Сегодняшнее видео закрывает этот вопрос:

  • Объясняем, чем механизм, который появился в 8.3.11, отличается от стандартного способа реструктуризации
  • Показываем, как настроить и использовать новый механизм
  • Демонстрируем его преимущества и рассказываем о его недостатках
  • Объясняем, кому необходим этот механизм, а кому переходить на него не стоит.

Если Вы недовольны тем, с какой скоростью проходит реструктуризация в ваших базах, это видео обязательно к просмотру.

Но даже если Вы работаете в маленькой компании и с этой проблемой еще не столкнулись – рекомендуем все-таки найти 17 минут и посмотреть его. Если завтра Вы поменяете работу и столкнетесь с такой проблемой – не придется волноваться из-за того, что Вы не в курсе таких нюансов.

Ключевые моменты видео:

  • 00:00 – Постановка задачи
  • 00:28 – Старый способ реструктуризации и его недостатки
  • 01:50 – Новый способ реструктуризации
  • 02:17 – Плюсы нового способа
  • 03:04 – Установка Java на сервер 1С
  • 04:18 – Настройка файла conf.cfg на клиенте
  • 05:40 – Демонстрация работы старого механизма
  • 07:36 – Демонстрация работы нового механизма
  • 08:58 – Особенности использования нового механизма
  • 09:10 – Включение протокола TCP/IP для СУБД
  • 10:52 – Проверка сторонних индексов
  • 13:20 – Настройка параметра MAXDOP в MS SQL
  • 16:36 – Итоги

Умение находить и устранять причины медленной и нестабильной работы систем на 1С обязательно для программистов 1С

После курса Вы сможете:

  • Оценивать состояние системы в любой момент времени
  • Быстро находить причины замедления в программном коде – и сразу писать его так, чтобы замедления в будущем не было
  • Отслеживать динамику производительности за определенный период
  • Устранять ожидания на блокировках и решать проблемы со взаимоблокировками

Для кого этот курс

Комментарии / обсуждение (48):

Подскажите пожалуйста, при обновлении пишет “”The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption” when trying to connect to a database”. В чем может быть проблема??

В процессе обновления конфигурации базы данных при работе оптимизированного механизма обновления произошла критическая ошибка
по причине:
Критическая ошибка работы Java-процесса.
Путь к Java: c:Program FilesJavajre1.8.0_171binjava.exe
Действие: prepare
Process ID: 9088
Код возврата: 1
Ошибка: Exception in thread “main” java.lang.IllegalArgumentException: expected one element but was:
at com.google.common.collect.Iterators.getOnlyElement(Iterators.java:312)
at com._1c.dmf.v8.converters.attributes.extdimensions.ExtDimensionInActionConverter.getConvertExpression(ExtDimensionInActionConverter.java:62)
at com._1c.dmf.internal.comparator.AttributeComparisonContext.createConvertExpression(AttributeComparisonContext.java:116)
at com._1c.dmf.internal.comparator.AttributeComparisonContext.getConvertExpression(AttributeComparisonContext.java:90)
at com.google.common.collect.Maps.toMap(Maps.java:1119)
at com.google.common.collect.Maps.toMap(Maps.java:1097)
at com._1c.dmf.internal.comparator.ComparisonProcess.processEntity(ComparisonProcess.java:150)
at java.lang.Iterable.forEach(Unknown Source)
at com._1c.dmf.internal.comparator.Comparator.compare(Comparator.java:35)
at com._1c.dmf.v8.internal.integration.DmfService.prepareMigration(DmfService.java:67)
at com._1c.dmf.v8.cli.Migration.run(Migration.java:90)
at com._1c.dmf.v8.cli.Migration.main(Migration.java:65)
Подскажите в чем может быть ошибка? ТиИ запустил и оно прошло успешно ошибок не нашлось. из конфы удаляются справочники которые входят в состав составного типа.

Попробуйте поставить Java версии 171 или младше.

ну вообще как раз 171 и стоит. как оказалось проблема в самой платформе и решили ее только на 8.3.21. т.е. после обновления платформы все заработало. причем в 8.3.21 есть уже свой JRE в комплекте

Ильшат, спасибо за информацию!

Что по поводу файловых баз, можно ли так ускорить обновление?

Честно говоря не могу сказать, просто файловые базы сами по себе не такие большие по объему и там не настолько критична проблема долгого обновления.

Платформа 8.3.20.1838, включил оптимизированный механизм обновления данных. при попытки изменения (реструктуризации) базы получил ошибку ” Multiple entries with same key: reference=reference:null and reference=reference:null” . (упп конфа). как исправить такую ошибку?

Попробуйте запустить Тестирование и исправление с исправлением ошибок.

Если в conf строка добавлена, а на сервере JRE не установлен, то при запуска реструктуризации что будет происходить?

Вероятнее всего будет ошибка с сообщением что не установлена JRE.

Настроил использование нового механизма реструктуризации, на SQL 2012 все работает, на SQL 2008 выдает ошибку (см. текст), настраивал исключение для java в брандмауэре, но не помогло.
Подскажите, в чем может быть причина?

В процессе обновления конфигурации базы данных при работе оптимизированного механизма обновления произошла критическая ошибка
по причине:
Критическая ошибка работы Java-процесса.
Путь к Java: C:Program FilesBellSoftLibericaJRE-8-Fullbinjava.exe
Действие: prepare
Process ID: 8484
Код возврата: 1
Ошибка: Exception in thread “main” com._1c.dmf.v8.cli.ApplicationException: com.microsoft.sqlserver.jdbc.SQLServerException: The connection to the host (local), named instance INST018 failed. Error: “java.net.UnknownHostException: (local)”. Verify the server and instance names and check that no firewall is blocking UDP traffic to port 1434. For SQL Server 2005 or later, verify that the SQL Server Browser Service is running on the host.
at com._1c.dmf.v8.cli.jdbc.mssql.MsSqlDataSourceFactory.getYearOffset(MsSqlDataSourceFactory.java:105)
at com._1c.dmf.v8.cli.jdbc.mssql.MsSqlDataSourceFactory.create(MsSqlDataSourceFactory.java:51)
at com._1c.dmf.v8.cli.Migration.run(Migration.java:81)
at com._1c.dmf.v8.cli.Migration.main(Migration.java:65)
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The connection to the host (local), named instance INST018 failed. Error: “java.net.UnknownHostException: (local)”. Verify the server and instance names and check that no firewall is blocking UDP traffic to port 1434. For SQL Server 2005 or later, verify that the SQL Server Browser Service is running on the host.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:227)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.getInstancePort(SQLServerConnection.java:5241)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.primaryPermissionCheck(SQLServerConnection.java:1916)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:1669)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:1528)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:866)
at com.microsoft.sqlserver.jdbc.SQLServerDataSource.getConnectionInternal(SQLServerDataSource.java:968)
at com.microsoft.sqlserver.jdbc.SQLServerDataSource.getConnection(SQLServerDataSource.java:69)
at com._1c.dmf.v8.cli.jdbc.V8DataSource.getConnection(V8DataSource.java:36)
at com._1c.dmf.v8.cli.jdbc.mssql.MsSqlDataSourceFactory.getYearOffset(MsSqlDataSourceFactory.java:86)
… 3 more

Здравствуйте.
У вас в 2008-м разрешены подключения по сети?
Судя по ошибке не доступен инстанс или не запущена служба SQL Server Browser Service.

Источник

1с критическая ошибка работы java процесса

Речь идёт о настройке для серверных баз, которая расположена в свойствах базы на закладке «Обновление» в разделе «Сам процесс»:

Версия механизма реструктуризации

Значение «из conf.cfg» означает, что обновлятор при выполнении пакетного обновления не указывает конкретной версии механизма реструктуризации, который следует использовать. В этом случае сервер 1с полагается на настройки конфигурационного файла conf.cfg (см. описание параметра UpdateDBCfg). Если параметр UpdateDBCfg в конфигурационных файлах (сервера и клиента) не описан — используется 1-я версия механизма реструктуризации (v1).

Значение «v1» означает 1-ю версию механизма реструктуризации, которая используется по умолчанию.

Значение «v2» означает 2-ю оптимизированную версию механизма реструктуризации, которая описана, например, здесь и здесь.

Параллелизм СУБД в процессе реструктуризации

Изменение параллелизма СУБД на время реструктуризации подробно описано здесь.

В обновляторе этот механизм реализован пока только для MS SQL Server.

Первое число означает значение параметра maxdop, которое обновлятор устанавливает на время выполнения обновления базы данных. Второе число означает значение этого же параметра, которое обновлятор устанавливает после выполнения реструктуризации.

Очевидно, что менять параллелизм для сервера СУБД через обновлятор имеет смысл только при однопоточном выполнении операций.

Как получать полное описание ошибки при работе оптимизированного механизма реструктуризации (v2)

При использовании второй (оптимизированной) версии механизма реструктуризации вы можете столкнуться с ситуацией, когда в отчёт попадает не вся информация об ошибке:

Мы видим, что при использовании оптимизированного механизма обновления произошла критическая ошибка, но не видим подробной информации об этой ошибке.

В этом случае можно выполнить эту же операцию интерактивно через конфигуратор — там будет полный текст ошибки.

Но я советую поступить по-другому.

Если вы планируете использовать второй механизм для реструктуризации базы данных, то лучше заблаговременно настроить на клиенте (там где стоит обновлятор) технологический журнал для сбора и кратковременного хранения информации об исключительных ситуациях при работе конфигуратора.

Файл настройки logcfg.xml для сбора данных конф. журнала будет таким: ссылка.

Значение параметра history равное 48 означает, что данные технологического журнала будет хранится на диске за последние 48 часов.

Значение параметра location равное «c:log1c» означает путь к папке, куда 1с будет записывать данные технологического журнала. Данная папка должна быть уже создана и пользователь, под которым работает обновлятор должен иметь права на запись в эту папку.

Да, я рекомендую настроить сбор технологического журнала именно на клиенте. Этого нам будет достаточно, так как ошибка реструктуризации будет возвращаться конфигуратором на стороне клиента. По этой же причине в файле настройки я намеренно устанавливаю фильтр на процесс «1cv8».

Разместить файл logcfg.xml удобней всего для конкретного пользователя операционной системы, под которым запускается обновлятор (и соотв. конфигуратор для пакетных операций), в папке «C:UsersusernameAppDataLocal1C1cv8conf».

После этого при возникновении ошибки реструктуризации в указанной нами папке для сбора данных мы сможем найти (по дате и времени) соотв. файл с подробным описанием ошибки, например:

Искать можно по фразе «в процессе обновления конфигурации базы данных при работе оптимизированного механизма».

В данном конкретном случае причина ошибки — не был запущен сервис «SQL Server Browser».

По каким причинам может не работать второй механизм реструктуризации

Прежде всего на сервере 1с должна быть установлена среда исполнения Java 8 Full JRE той же битности, что и сам сервер 1с.

К SQL серверу должно быть возможно подключение по протоколу TCP/IP (для MS SQL Server этот параметр настраивается в SQL Server Configuration Manager в разделе SQL Server Network Configuration).

Для MS SQL Server версии 2005 и позднее должна быть запущена служба SQL Server Browser.

Могут быть и более специфичные причины ошибок, связанные непосредственно с базой данных (например, индексы отличные от стандартных). В этом случае я советую собрать подробную информацию по ошибке из технологического журнала. И если всё-равно не получится разобраться самому — обращаться с этой информацией в службу технической поддержки 1с.

С уважением, Владимир Милькин (преподаватель школы 1С программистов и разработчик обновлятора).

Подписывайтесь и получайте новые статьи и обработки на почту (не чаще 1 раза в неделю).

Вступайте в мою группу ВКонтакте, Одноклассниках, Facebook или Google+ — самые последние обработки, исправления ошибок в 1С, всё выкладываю там в первую очередь.

Как помочь сайту: расскажите (кнопки поделиться ниже) о нём своим друзьям и коллегам. Сделайте это один раз и вы внесете существенный вклад в развитие сайта. На сайте нет рекламы, но чем больше людей им пользуются, тем больше сил у меня для его поддержки.

Нажмите одну из кнопок, чтобы поделиться:

Источник

Исключения

  • Исключения
    • Введение
    • Иерархия исключений
      • Проверяемые и непроверяемые
      • Иерархия
        • Классификация
        • Error и Exception
    • Работа с исключениями
      • Обработка исключений
        • Правила try/catch/finally
        • Расположение catch блоков
        • Транзакционность
      • Делегирование
      • Методы и практики работы с исключительными ситуацими
        • Собственные исключения
        • Реагирование через re-throw
        • Не забывайте указывать причину возникновения исключения
        • Сохранение исключения
        • Логирование
        • Чего нельзя делать при обработке исключений
      • Try-with-resources или try-с-ресурсами
      • Общие советы
        • Избегайте генерации исключений, если их можно избежать простой проверкой
        • Предпочитайте Optional, если отсутствие значения — не исключительная ситуация
        • Заранее обдумывайте контракты методов
        • Предпочитайте исключения кодам ошибок и boolean флагам-признакам успеха
    • Исключения и статические блоки
    • Многопоточность и исключения
    • Проверяемые исключения и их необходимость
    • Заключение
    • Полезные ссылки

Введение

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

(c) Морис Уилкс.

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

    public List<String> readAll(String path) {
BufferedReader br = new BufferedReader(new FileReader(path));
String line;
List<String> lines = new ArrayList<>();
while ((line = br.readLine()) != null) {
lines.add(line);
}
return lines;
}

И это был бы вполне рабочий вариант, если бы не одно но: мы живём не в идеальном мире. Код, приведённый выше, рассчитан на то, что всё работает идеально: путь до файла указан верный, файл можно прочитать, во время чтения с файлом ничего не происходит, место хранения файла работает без ошибок и еще огромное количество предположений.

Однако, как показывает практика, мир не идеален, а нас повсюду преследуют ошибки и проблемы. Кто-то может указать путь до несуществующего файла, во время чтения может произойти ошибка, например, файл повреждён или удален в процессе чтения и т.д.

Игнорирование подобных ситуаций недопустимо, так как это ведет к нестабильно и непредсказуемо работающему коду.
Значит, на такие ситуации надо реагировать.

Самая простая реакция — это возвращать boolean — признак успеха или некоторый код ошибки, например, какое-то число.
Пусть, 0 — это код удачного завершения приложения, 1 — это аварийное завершение и т.д.
Мы получаем код возврата и уже на него реагируем.

Подобный ход имеет право на жизнь, однако, он крайне неудобен в повседневной разработке с её тысячами возможных ошибок и проблемных ситуаций.

Во-первых, он слишком немногословен, так как необходимо помнить что означает каждый код возврата, либо постоянно сверяться с таблицей расшифровки, где они описаны.

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

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

Lots of newbie’s coming in from the C world complain about exceptions and the fact that they have to put exception handling all over the place—they want to just write their code. But that’s stupid: most C code never checks return codes and so it tends to be very fragile. If you want to build something really robust, you need to pay attention to things that can go wrong, and most folks don’t in the C world because it’s just too damn hard.
One of the design principles behind Java is that I don’t care much about how long it takes to slap together something that kind of works. The real measure is how long it takes to write something solid.

In Java you can ignore exceptions, but you have to willfully do it. You can’t accidentally say, «I don’t care.» You have to explicitly say, «I don’t care.»

(c) James Gosling.

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

Что такое исключение? В некотором смысле можно сказать, что исключение — это некоторое сообщение, уведомляющее о проблеме, незапланированном поведении.

В нашем примере с чтением содержимого файла, источником такого сообщения может являться BufferedReader или FileReader. Сообщению необходим получатель/обработчик, чтобы перехватить его и что-то сделать, как-то отреагировать.

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

Что значит «ломает поток выполнения программы»?

Представьте, что по дороге едет грузовик. Движение машины и есть поток выполнения программы. Вдруг водитель видит, что впереди разрушенный мост — исключение, ошибка. Теперь он либо поедет по объездной дороге, т.е перехватит и отреагирует на исключение, либо остановится и поездка будет завершена.

Объездная

Исключения могут быть разных типов, под разные ситуации, а значит и получателей(обработчиков) может быть несколько — на каждый отдельный тип может быть своя реакция, свой обработчик.

Исключение также может хранить информацию о возникшей проблеме: причину, описание-комментарий и т.д.
Исходя из описания можно сказать, что исключение — это объект некоторого, специально для этого предназначенного, класса. Так как проблемы и ошибки бывают разного рода, их можно классифицировать и логически разделить, значит и классы исключений можно выстроить в некоторую иерархию.

Как генерировать исключения и регистрировать обработчики мы рассмотрим позднее, а пока давайте взглянем на иерархию этих классов.

Иерархия исключений

Ниже приведена иерархия исключений:

Exception Hierarchy

Картинка большая, чтобы лучше запоминалась.

Для начала разберем загадочные подписи checked и unchecked на рисунке.

Проверяемые и непроверяемые

Все исключения в Java делятся на два типа: проверяемые (checked) и непроверяемые исключения (unchecked).

Как видно на рисунке, java.lang.Throwable и java.lang.Exception относятся к проверяемым исключениям, в то время как java.lang.RuntimeException и java.lang.Error — это непроверяемые исключения.

Принадлежность к тому или иному типу каждое исключение наследует от родителя.
Это значит, что наследники java.lang.RuntimeException будут unchecked исключениями, а наследники java.lang.Exceptionchecked.

Что это за разделение?

В первую очередь напомним, что Java — это компилируемый язык, а значит, помимо runtime(время выполнения кода), существует ещё и compile-time(то, что происходит во время компиляции).

Так вот проверяемые исключения — это исключения, на которые разработчик обязан отреагировать, т.е написать обработчики, и наличие этих обработчиков будет проверено на этапе компиляции. Ваш код не будет скомпилирован, если какое-то проверяемое исключение не обработано, компилятор этого не допустит.

Непроверяемые исключения — это исключения времени выполнения. Компилятор не будет от вас требовать обработки непроверяемых исключений.

В чём же смысл этого разделения на проверяемые и непроверяемые исключения?

Я думаю так: проверяемые исключения в Java — это ситуации, которые разработчик никак не может предотвратить и исключение является одним из вариантов нормальной работы кода.

Например, при чтении файла требуется обрабатывать java.io.FileNotFoundException и java.io.IOException, которые является потомками java.io.Exception.

Потому, что отсутствие файла или ошибка работы с вводом/выводом — это вполне допустимая ситуация при чтении.

С другой стороны, java.lang.RuntimeException — это скорее ошибки разработчика.
Например, java.lang.NullPointerException — это ошибка обращения по null ссылке, данную ситуацию можно предотвратить: проверить ссылку на null перед вызовом.

Представьте, что вы едете по дороге, так вот предупредительные знаки — это проверяемые исключения. Например, знак «Осторожно, дети!» говорит о том, что рядом школа и дорогу может перебежать ребенок. Вы обязаны отреагировать на это, не обязательно ребенок перебежит вам дорогу, но вы не можете это проконтролировать, но в данном месте — это нормальная ситуация, ведь рядом школа.

Делать абсолютно все исключения проерямыми — не имеет никакого смысла, потому что вы просто с ума сойдете, пока будете писать обработчики таких ситуаций. Да и зачастую это будет только мешать: представьте себе дорогу, которая утыкана постоянными предупредительными знаками, на которые вы должны реагировать. Ехать по такой дороге будет крайне утомительно.

Разделение на проверяемые и непроверяемые исключения существует только в Java, в других языках программирования, таких как Scala, Groovy, Kotlin или Python, все исключения непроверяемые.

Это довольно холиварная тема и свои мысли по ней я изложу в конце статьи.

Теперь рассмотрим непосредственно иерархию исключений.

Иерархия

Итак, корнем иерархии является java.lang.Throwable, у которого два наследника: java.lang.Exception и java.lang.Error.
В свою очередь java.lang.Exception является родительским классом для java.lang.RuntimeException.

Занятно, что класс java.lang.Throwable назван так, как обычно называют интерфейсы, что иногда вводит в заблуждение новичков. Однако помните, что это класс! Запомнить это довольно просто, достаточно держать в уме то, что исключения могут содержать состояние (например, информация о возникшей проблеме).

Так как в Java все классы являются наследниками java.lang.Object, то и исключения (будучи тоже классами) наследуют все стандартные методы, такие как equals, hashCode, toString и т.д.

Раз мы работаем с классами, то можно с помощью наследования создавать свои собственные иерархии исключений, добавляя в них какое-то специфическое поведение и состояние.

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

Классификация

Каждый тип исключения отвечает за свою область ошибок.

  1. java.lang.Exception

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

    Это проверяемые исключения, мы обязаны на такие исключения реагировать, это будет проверено на этапе компиляции.

    Пример: java.io.IOException, java.io.FileNotFoundException.

  2. java.lang.RuntimeException

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

    Это непроверяемые исключения, реагировать на них или нет решает разработчик.

    Пример: java.lang.NullPointerException.

  3. java.lang.Error

    Это критические ошибки, аварийные ситуации, после которых мы с трудом или вообще не в состоянии продолжить работу. Например, закончилась память, переполнился стек вызовов и т.д.

    Это непроверяемые исключения, реагировать на них или нет решает разработчик.

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

Теперь перейдем к вопросу: в чем же разница между java.lang.Error и java.lang.Exception?

Error и Exception

Все просто. Исключения java.lang.Error — это более серьезная ситуация, нежели java.lang.Exception.
Это серьезные проблемы в работе приложения, которые тяжело исправить, либо вообще неясно, можно ли это сделать.

Это не просто исключительная ситуация — это ситуация, в которой работоспособность всего приложения под угрозой! Например, исключение java.lang.OutOfMemoryError, сигнализирующее о том, что кончается память или java.lang.StackOverflowError – переполнение стека вызовов, которое можно встретить при бесконечной рекурсии.

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

Т.е разница — в логическом разделении.

Поэтому, java.lang.Error и его наследники используются только для критических ситуаций.

Работа с исключениями

Обработка исключений

Корнем иерархии является класс java.lang.Throwable, т.е. что-то «бросаемое».
А раз исключения бросаются, то для обработки мы будем ловить их!

В Java исключения ловят и обрабатывают с помощью конструкции try/catch/finally.

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

В блоках catch перечисляются исключения, на которые решено реагировать. Тут определяются блоки кода, предназначенные для решения возникших проблем. Это и есть объявление тех самых получателей/обработчиков исключений.

Пример:

public class ExceptionHandling {
public static void main(String[] args) {
try {
// код
} catch(FileNotFoundException fnf) {
// обработчик на FileNotFoundException
}
}
}

Тот тип исключения, что указывается в catch блоке можно расценивать как фильтр, который перехватывает все исключения того типа, что вы указали и всех его потомков, расположенных ниже по иерархии.

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

Точно также и в Java, ставя фильтр на java.lang.RuntimeException вы ловите не только java.lang.RuntimeException, но и всех его наследников! Ведь эти потомки — это тоже runtime ошибки!

В блоке finally определяется код, который будет всегда выполнен, независимо от результата выполнения блоков try/catch. Этот блок будет выполняться независимо от того, выполнился или нет блок try до конца, было ли сгенерировано исключение или нет, и было ли оно обработано в блоке catch или нет.

Пример:

public class ExceptionHandling {
public static void main(String[] args) {
try {
// some code
} catch(FileNotFoundException fnf) {
// обработчик 1
} catch(RuntimeException re) {
// обработчик 2
} finally {
System.out.println("Hello from finally block.");
}
}
}

В примере выше объявлен try блок с кодом, который потенциально может сгенерировать исключения, после try блока описаны два обработчика исключений, на случай генерации FileNotFoundException и на случай генерации любого RuntimeException.
Объект исключения доступен по ссылке exception.

Правила try/catch/finally

  1. Блок try находится перед блоком catch или finally. При этом должен присутствовать хотя бы один из этих блоков.

  2. Между try, catch и finally не может быть никаких операторов.

  3. Один блок try может иметь несколько catch блоков. В таком случае будет выполняться первый подходящий блок.

    Поэтому сначала должны идти более специальные блоки обработки исключений, а потом уже более общие.

  4. Блок finally будет выполнен всегда, кроме случая, когда JVM преждевременно завершит работу или будет сгенерировано исключение непосредственно в самом finally блоке.

  5. Допускается использование вложенных конструкций try/catch/finally.

    public class ExceptionHandling {
    public static void main(String[] args) {
    try {
    try {
    // some code
    } catch(FileNotFoundException fnf) {
    // обработчик 1
    }
    } catch(RuntimeException re) {
    // обработчик 2
    } finally {
    System.out.println("Hello from finally block.");
    }
    }
    }

Вопрос:

Каков результат выполнения примера выше, если в блоке try не будет сгенерировано ни одного исключения?

Ответ:

Будет выведено на экран: «Hello from finally block.».

Так как блок finally выполняется всегда.


Вопрос:

Теперь немного видоизменим код, каков результат выполнения будет теперь?

public class ExceptionHandling {
public static void main(String[] args) {
try {
return;
} finally {
System.out.println("Hello from finally block");
}
}
}

Ответ:

На экран будет выведено: Hello from finally block.


Вопрос:

Плохим тоном считается прямое наследование от java.lang.Throwable.
Это строго не рекомендуется делать, почему?

Ответ:

Наследование от наиболее общего класса, а в данном случае от корневого класса иерархии, усложняет обработку ваших исключений. Проблему надо стараться локализовать, а не делать ее описание/объявление максимально общим. Согласитесь, что java.lang.IllegalArgumentException говорит гораздо больше, чем java.lang.RuntimeException. А значит и реакция на первое исключение будет более точная, чем на второе.


Далее приводится несколько примеров перехвата исключений разных типов:

Обработка java.lang.RuntimeException:

try {
String numberAsString = "one";
Double res = Double.valueOf(numberAsString);
} catch (RuntimeException re) {
System.err.println("Error while convert string to double!");
}

Результатом будет печать на экран: Error while convert string to double!.

Обработка java.lang.Error:

try {
throw new Error();
} catch (RuntimeException re) {
System.out.println("RuntimeException");
} catch (Error error) {
System.out.println("ERROR");
}

Результатом будет печать на экран: ERROR.

Расположение catch блоков

Как уже было сказано, один блок try может иметь несколько catch блоков. В таком случае будет выполняться первый подходящий блок.

Это значит, что порядок расположения catch блоков важен.

Рассмотрим ситуацию, когда некоторый используемый нами метод может выбросить два разных исключения:

void method() throws Exception {
if (new Random((System.currentTimeMillis())).nextBoolean()) {
throw new Exception();
} else {
throw new IOException();
}
}

Конструкция new Random((System.currentTimeMillis())).nextBoolean() генерирует нам случайное значение false или true.

Для обработки исключений этого метода написан следующий код:

try {
method();
} catch (Exception e) {
// Обработчик 1
} catch (IOException e) {
// Обработчик 2
}

Все ли хорошо с приведенным выше кодом?
Нет, код выше неверен, так как обработчик java.io.IOException в данном случае недостижим. Все дело в том, что первый обработчик, ответсвенный за Exception, перехватит все исключения, а значит не может быть ситуации, когда мы сможем попасть во второй обработчик.

Снова вспомним пример с мукой, приведенный в начале.

Так вот песчинка, которую мы ищем, это и есть наше исключение, а каждый фильтр это catch блок.

Если первым установлен фильтр ловить все, что является Exception и его потомков, то до фильтра ловить все, что является IOException и его потомков ничего не дойдет, так как верхний фильтр уже перехватит все песчинки.

Отсюда следует правило:

Сначала должны идти более специальные блоки обработки исключений, а потом уже более общие.

А что если на два разных исключения предусмотрена одна и та же реакция? Написание двух одинаковых catch блоков не приветствуется, ведь дублирование кода — это зло.

Поэтому допускается объединить два catch блока с помощью |:

try {
method2();
} catch (IllegalArgumentException | IndexOutOfBoundsException e) {
// Обработчик
}

Вопрос:

Есть ли способ перехватить все возможные исключения?

Ответ:

Есть! Если взглянуть еще раз на иерархию, то можно отметить, что java.lang.Throwable является родительским классом для всех исключений, а значит, чтобы поймать все, необходимо написать что-то в виде:

try {
method();
} catch (Throwable t) {
// Обработчик
}

Однако, делать так не рекомендуется, что наталкивает на следующий вопрос.


Вопрос:

Почему перехватывать java.lang.Throwable — плохо?

Ответ:

Дело в том, что написав:

try {
method();
} catch (Throwable t) {
// catch all
}

Будут перехвачены абсолютно все исключения: и java.lang.Exception, и java.lang.RuntimeException, и java.lang.Error, и все их потомки.

И как реагировать на все? При этом надо учесть, что обычно на java.lang.Error исключений вообще не ясно как реагировать. А значит, мы можем неверно отреагировать на исключение и вообще потерять данные. А ловить то, что не можешь и не собирался обрабатывать — плохо.

Поэтому перехватывать все исключения — плохая практика.


Вопрос-Тест:

Что будет выведено на экран при запуске данного куска кода?

public static void main(String[] args) {
try {
try {
throw new Exception("0");
} finally {
if (true) {
throw new IOException("1");
}
System.err.println("2");
}
} catch (IOException ex) {
System.err.println(ex.getMessage());
} catch (Exception ex) {
System.err.println("3");
System.err.println(ex.getMessage());
}
}

Ответ:

При выполнении данного кода выведется «1».
Давайте разберем почему.

Мы кидаем исключение во вложенном try блоке: throw new Exception("0");.

После этого поток программы ломается и мы попадаем в finally блок:

if (true) {
throw new IOException("1");
}
System.err.println("2");

Здесь мы гарантированно зайдем в if и кинем уже новое исключение: throw new IOException("1");.
При этом вся информация о первом исключении будет потеряна! Ведь мы никак не отреагировали на него, а в finally блоке и вовсе ‘перезатерли’ новым исключением.

На try, оборачивающий наш код, настроено два фильтра: первый на IOException, второй на Exception.

Так как порядок расположения задан так, что мы прежде всего смотрим на IOException, то и сработает этот фильтр, который выполнит следующий код:

System.err.println(ex.getMessage());

Именно поэтому выведется 1.


Транзакционность

Важным моментом, который нельзя пропустить, является то, что try блок не транзакционный.

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

Что это значит?

Это значит, что при возникновении исключения в try блоке все совершенные действия не откатываются к изначальному состоянию, а так и остаются совершенными.
Все выделенные ресурсы так и остаются занятыми, в том числе и при возникновении исключения.

По сути именно поэтому и существует finally блок, так как туда, как уже было сказано выше, мы зайдем в любом случае, то там и освобождают выделенные ресурсы.


Вопрос:

Работа с объектами из try блока в других блоках невозможна:

public class ExceptionExample {
public static void main(String[] args) {
try {
String line = "hello";
} catch (Exception e) {
System.err.println(e);
}
// Compile error
System.out.println(line); // Cannot resolve symbol `line`
}
}

Почему?

Ответ:

Потому что компилятор не может нам гарантировать, что объекты, объявленные в try-блоке, были созданы.

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


Вернемся к примеру с грузовиком, чтобы объяснить все вышесказанное.

Объездная

Объездная здесь — это catch блок, реакция на исключительную ситуацию. Если добавить еще несколько объездных дорог, несколько catch блоков, то водитель выберет наиболее подходящий путь, наиболее подходящий и удобный catch блок, что объясняет важность расположения этих блоков.

Транзакционность на этом примере объясняется тем, что если до этого водитель где-то оплатил проезд по мосту, то деньги ему автоматически не вернутся, необходимо будет написать в поддержку или куда-то пожаловаться на управляющую компанию.

Делегирование

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

Делегирование исключения производится с помощью ключевого слова throws, которое добавляется после сигнатуры метода.

Пример:

// Код написан только для ознакомительной цели, не стоит с него брать пример!
String readLine(String path) throws IOException {
BufferedReader br = new BufferedReader(...);
String line = br.readLine();
return line;
}

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

Механизм throws введен для проброса проверяемых исключений.

Разумеется, с помощью throws можно описывать делегирование как проверяемых, так и непроверяемых исключений.
Однако перечислять непроверяемые не стоит, такие исключения не контролируются в compile time.

Перечисление непроверяемых исключений бессмысленно, так как это примерно то же самое, что перечислять все, что может с вами случиться на улице.

Теперь пришла пора рассмотреть методы обработки исключительных ситуаций.

Методы и практики работы с исключительными ситуацими

Главное и основное правило при работе с исключениями звучит так:

На исключения надо либо реагировать, либо делегировать, но ни в коем случае не игнорировать.

Определить когда надо реагировать, а когда делегировать проще простого. Задайте вопрос: «Знаю ли я как реагировать на это исключение?».

Если ответ «да, знаю», то реагируйте, пишите обработчик и код, отвечающий за эту реакцию, если не знаете что делать с исключением, то делегируйте вызывающему коду.

Собственные исключения

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

Например, пусть есть некоторый справочник:

class Catalog {
Person findPerson(String name);
}

В данном случае нам надо обработать ситуации, когда name является null, когда в каталоге нет пользователя с таким именем.

Если генерировать на все ситуации java.lang.Exception, то обработка ошибок будет крайне неудобной.
Более того, хотелось бы явно выделить ошибку, связанную с тем, что пользователя такого не существует.
Очевидно, что стандартное исключение для этого случая не существует, а значит вполне логично создать свое.

class PersonNotFoundException extends RuntimeException {
private String name;
// some code
}

Обратите внимание, что имя Person, по которому в каталоге не смогли его найти, выделено в свойство класса name.

Теперь при использовании этого метода проще реагировать на различные ситуации, такие как null вместо имени, а проблему с отсутствием Person в каталоге можно отдельно вынести в свой catch блок.

Реагирование через re-throw

Часто бывает необходимо перехватить исключение, сделать запись о том, что случилось (в файл лога, например) и делегировать его вызывающему коду.
Как уже было сказано выше, в рамках конструкции try/catch/finally можно сгенерировать другое исключение.

Такой подход называется re-throw.

Исключение перехватывается в catch блоке, совершаются необходимые действия, например, запись в лог или создание нового, более конкретного для контекста задачи, исключения и повторная генерация исключения.

Как это выглядит на практике:

try {
Reader readerConf = ....
readerConf.readConfig();
} catch(IOException ex) {
System.err.println("Log exception: " + ex);
throw new ConfigException(ex);
}

Во время чтения конфигурационного файла произошло исключение java.io.IOException, в catch блоке оно было перехвачено, сделана запись в консоль о проблеме, после чего было создано новое, более конкретное, исключение ConfigException, с указанием причины (перехваченное исключение, ссылка на которое ex) и оно было проброшено дальше.

По итогу, из метода с приведенным кодом, в случае ошибки чтения конфигурации, будет выброшено ConfigException.

Для чего мы здесь так поступили?

Это полезно для более гибкой обработки исключений.
В примере выше чтение конфигурации генерирует слишком общее исключение, так как java.io.IOException это довольно общее исключение, но проблема в примере выше понятна: работа с этим конфигурационным файлом невозможна.

Значит и сообщить лучше именно как о том, что это не абстрактный java.io.IOException, а именно ConfigException. При этом, так как перехваченное исключение было передано новому в конструкторе, т.е. указалась причина возникновения (cause) ConfigException, то при выводе на консоль или обработке в вызывающем коде будет понятно почему ConfigException был создан.

Также, можно было добавить еще и текстовое описание к сгенерированному ConfigException, более подробно описывающее произошедшую ситуацию.

Еще одной важной областью применения re-throw бывает преобразование проверяемых исключений в непроверяемые.
В Java 8 даже добавили исключение java.io.UncheckedIOException, которое предназначено как раз для того, чтобы сделать java.io.IOException непроверяемым, обернуть в unchecked обертку.

Пример:

try {
Reader readerConf = ....
readerConf.readConfig();
} catch(IOException ex) {
System.err.println("Log exception: " + ex);
throw new UncheckedIOException(ex);
}

Не забывайте указывать причину возникновения исключения

В предыдущем пункте мы создали собственное исключение, которому указали причину: перехваченное исключение, java.io.IOException.

Чтобы понять как это работает, давайте рассмотрим наиболее важные поля класса java.lang.Throwable:

public class Throwable implements Serializable {
/**
     * Specific details about the Throwable.  For example, for
     * {@code FileNotFoundException}, this contains the name of
     * the file that could not be found.
     *
     * @serial
     */
private String detailMessage;
// ...
/**
     * The throwable that caused this throwable to get thrown, or null if this
     * throwable was not caused by another throwable, or if the causative
     * throwable is unknown.  If this field is equal to this throwable itself,
     * it indicates that the cause of this throwable has not yet been
     * initialized.
     *
     * @serial
     * @since 1.4
     */
private Throwable cause = this;
// ...
}

Все исключения, будь то java.lang.RuntimeException, либо java.lang.Exception имеют необходимые конструкторы для инициализации этих полей.

При создании собственного исключения не пренебрегайте этими конструкторами!

Поле cause используются для указания родительского исключения, причины. Например, выше мы перехватили java.io.IOException, прокинув свое исключение вместо него. Но причиной того, что наш код выкинул ConfigException было именно исключение java.io.IOException. И эту причину нельзя игнорировать.

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

Для получения причины возникновения исключения существует метод getCause.

public class ExceptionExample {
public Config readConfig() throws ConfigException { // (1)
try {
Reader readerConf = ....;
readerConf.readConfig();
} catch (IOException ex) {
System.err.println("Log exception: " + ex);
throw new ConfigException(ex); // (2)
}
}
public void run() {
try {
Config config = readConfig(); // (3)
} catch (ConfigException e) {
Throwable t = e.getCause(); // (4)
}
}
}

В коде выше:

  1. В строке (1) объявлен метод readConfig, который может выбросить ConfigException.
  2. В строке (2) создаётся исключение ConfigException, в конструктор которого передается IOException — причина возникновения.
  3. readConfig вызывается в (3) строке кода.
  4. А в (4) вызван метод getCause который и вернёт причину возникновения ConfigExceptionIOException.

Сохранение исключения

Исключения необязательно генерировать, пробрасывать и так далее.
Выше уже упоминалось, что исключение — это Java-объект. А значит, его вполне можно присвоить переменной или свойству класса, передать по ссылке в метод и т.д.

class Reader {
// A holder of the last IOException encountered
private IOException lastException;
// some code
public void read() {
try {
Reader readerConf = ....
readerConf.readConfig();
} catch(IOException ex) {
System.err.println("Log exception: " + ex);
lastException = ex;
}
}
}

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

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

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

Например, идет запись в базу данных тысячу строк построчно.
Из них 100 записей происходит с ошибкой.
Эти исключения складываются в список, а после этот список передается специальному методу, который по каждой ситуации из списка как-то отреагирует.
Т.е пока делаете операцию, копите ошибки, а потом уже реагируете.

Это похоже на то, как опрашивают 1000 человек, а негативные отзывы/голоса записывают, после чего реагируют на них. Согласитесь, было бы глупо после каждого негативного отзыва осуществлять реакцию, а потом снова возвращаться к толпе и продолжать опрос.

class Example {
private List<Exception> exceptions;
// some code
public void parse(String s) {
try {
// do smth
} catch(Exception ex) {
exceptions.add(ex);
}
}
private void handleExceptions()  {
for(Exception e : exceptions) {
System.err.println("Log exception: " + e);
}
}
}

Логирование

Когда логировать исключение?

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

Также, исключение может быть частью ожидаемого поведения. В этом случае нет необходимости его логировать.

Поэтому не стоит преждевременно логировать исключение, например:

/**
 * Parse date from string to java.util.Date.
 * @param date as string 
 * @return Date object.
 */
public static Date from(String date) {
try {
DateFormat format = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH);
return format.parse(date);
}  catch (ParseException e) {
logger.error("Can't parse ")
throw e;
}
}

Здесь ParseException является частью ожидаемой работы, в ситуациях, когда строка содержит невалидные данные.
Раз происходит делегирование исключения выше (с помощью throw), то и там, где его будут обрабатывать и лучше всего логировать, а эта запись в лог будет избыточной. Хотя бы потому, что в месте обработки исключения его тоже залогируют!

Подробнее о логировании.

Чего нельзя делать при обработке исключений

  1. Старайтесь не игнорировать исключения.

    В частности, никогда не пишите подобный код:

        try {
    Reader readerConf = ....
    readerConf.readConfig();
    } catch(IOException e) {
    e.printStackTrace();
    }
  2. Не следует писать ‘универсальные’ блоки обработки исключений.

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

    Также программный код может измениться, а ‘универсальный’ обработчик исключений будет продолжать обрабатывать новые типы исключений одинаково.

    Поэтому таких ситуаций лучше не допускать.

  3. Старайтесь не преобразовывать более конкретные исключения в более общие.

    В частности, например, не следует java.io.IOException преобразовывать в java.lang.Exception или в java.lang.Throwable.

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

  4. Старайтесь не злоупотреблять исключениями.

    Если исключение можно не допустить, например, дополнительной проверкой, то лучше так и сделать.

    Например, можно обезопасить себя от java.lang.NullPointerException простой проверкой:

      if(ref != null) {
    // some code
    }

Try-with-resources или try-с-ресурсами

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

Чаще всего за закрытие ресурса будет отвечать код, наподобие этого:

try {
// code
} finally {
resource.close();
}

Освобождение ресурса (например, освобождение файлового дескриптора) — это поведение.

А за поведение в Java отвечают интерфейсы.

Это наталкивает на мысль, что нужен некоторый общий интерфейс, который бы реализовывали все классы, для которых необходимо выполнить какой-то код по освобождению ресурсов, т.е выполнить ‘закрытие’ в finally блоке и еще удобнее, если бы этот однообразный finally блок не нужно было писать каждый раз.

Поэтому, начиная с Java 7, была введена конструкция try-with-resources или TWR.

Для этого объявили специальный интерфейс java.lang.AutoCloseable, у которого один метод:

void close() throws Exception;

Все классы, которые будут использоваться так, как было описано выше, должны реализовать или java.lang.Closable, или java.lang.AutoCloseable.

В качестве примера, напишем код чтения содержимого файла и представим две реализации этой задачи: используя и не используя try-with-resources.

Без использования try-with-resources (пример ниже плох и служит только для демонстрации объема необходимого кода):

BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(path));
// read from file
} catch (IOException e) {
// catch and do smth
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException ex) {
// catch and do smth
}
}

А теперь то же самое, но в Java 7+:

try (FileReader fr = new FileReader(path);
BufferedReader br = new BufferedReader(fr)) {
// read from file
} catch (IOException e) {
// catch and do smth
}

По возможности пользуйтесь только try-with-resources.

Помните, что без реализации java.lang.Closable или java.lang.AutoCloseable ваш класс не будет работать с try-with-resources так, как показано выше.


Вопрос:

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

Ответ:

Точно так же, как и без TWR, исключение выбросится так, будто оно было в finally-блоке.

Помните, что TWR, грубо говоря, просто добавляет вам блок кода вида:

finally {
resource.close();
}

Вопрос:

Является ли безопасной конструкция следующего вида?

try (BufferedWriter bufferedWriter
= new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a")))) {
}

Ответ:

Не совсем, если конструктор OutputStreamWriter или BufferedWriter выбросит исключение, то FileOutputStream закрыт не будет.

Пример, демонстрирующий это:

public class Main {
public static void main(String[] args) throws Exception {
try (ThrowingAutoCloseable throwingAutoCloseable
= new ThrowingAutoCloseable(new PrintingAutoCloseable())) { // (1)
}
}
private static class ThrowingAutoCloseable implements AutoCloseable { // (2)
private final AutoCloseable other;
public ThrowingAutoCloseable(AutoCloseable other) {
this.other = other;
throw new IllegalStateException("I always throw"); // (3)
}
@Override
public void close() throws Exception {
try {
other.close(); // (4)
} finally {
System.out.println("ThrowingAutoCloseable is closed");
}
}
}
private static class PrintingAutoCloseable implements AutoCloseable { // (5)
public PrintingAutoCloseable() {
System.out.println("PrintingAutoCloseable created"); // (6)
}
@Override
public void close() {
System.out.println("PrintingAutoCloseable is closed"); // (7)
}
}
}
  1. В строке (1) происходит заворачивание одного ресурса в другой, аналогично new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a"))).
  2. ThrowingAutoCloseable (2) — такой AutoCloseable, который всегда бросает исключение (3), в (4) производится попытка закрыть полученный в конструкторе AutoCloseable.
  3. PrintingAutoCloseable (5) — AutoCloseable, который печатает сообщения о своём создании (6) и закрытии (7).

В результате выполнения этой программы вывод будет примерно следующим:

PrintingAutoCloseable created
Exception in thread "main" java.lang.IllegalStateException: I always throw
at ru.misc.Main$ThrowingAutoCloseable.<init>(Main.java:19)
at ru.misc.Main.main(Main.java:9)

Как видно, PrintingAutoCloseable закрыт не был!


Вопрос:

В каком порядке закрываются ресурсы, объявленные в try-with-resources?

Ответ:

В обратном.

Пример:

public class Main {
public static void main(String[] args) throws Exception {
try (PrintingAutoCloseable printingAutoCloseable1 = new PrintingAutoCloseable("1");
PrintingAutoCloseable printingAutoCloseable2 = new PrintingAutoCloseable("2");
PrintingAutoCloseable printingAutoCloseable3 = new PrintingAutoCloseable("3")) {
}
}
private static class PrintingAutoCloseable implements AutoCloseable {
private final String id;
public PrintingAutoCloseable(String id) {
this.id = id;
}
@Override
public void close() {
System.out.println("Closed " + id);
}
}
}

Вывод:

Closed 3
Closed 2
Closed 1

Общие советы

Избегайте генерации исключений, если их можно избежать простой проверкой

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

Помните, что если исключение можно не допустить, то лучше так и сделать.

Отсюда следует первый совет: не брезгуйте дополнительными проверками.

  1. Не ловите IllegalArgumentException, NullPointerException, ArrayIndexOutOfBoundsException и подобные.
    Потому что эти ошибки — это явная отсылка к тому, что где-то недостает проверки.
    Обращение по индексу за пределами массива, NullPointerException, все эти исключения — это ошибка разработчика.
  2. Вводите дополнительные проверки на данные, дабы избежать возникновения непроверяемых исключения

Например, запретите вводить в поле возраста не числовые значения, проверяйте ссылки на null перед обращением и т.д.

Предпочитайте Optional, если отсутствие значения — не исключительная ситуация

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

class Catalog {
Person findPerson(String name);
}

Но и в этом случае генерации исключения можно избежать, если воспользоваться java.util.Optional:

Optional<Person> findPerson(String name);

Класс java.util.Optional был добавлен в Java 8 и предназначен как раз для подобных ситуаций, когда возвращаемого значения может не быть. В зависимости от задачи и контекста можно как генерировать исключение, как это сделано в примере с PersonNotFoundException, так и изменить сигнатуру метода, воспользовавшись java.util.Optional.

Отсюда следует второй совет: думайте над API ваших классов, исключений можно избежать воспользовавшись другим подходом.

Заранее обдумывайте контракты методов

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

class Person {
void hello() throws RuntimeException {
// some code
}
}
// Compile Error
class PPerson extends Person {
@Override
void hello() throws Exception {
// some code
}
}

Если было явно указано, что метод может сгенерировать java.lang.RuntimeException, то нельзя объявить более общее бросаемое исключение при переопределении. Но можно указать потомка:

// IllegalArgumentException - потомок RuntimeException!
class PPerson extends Person {
@Override
void hello() throws IllegalArgumentException {
// some code
}
}

Что, в целом логично.

Если объявляется, что метод может сгенерировать java.lang.RuntimeException, а он выбрасывает java.io.IOException, то это было бы как минимум странно.

Это объясняется и с помощью полимофризма. Пусть есть интерфейс, в котором объявлен метод, генерирующий исключение. Если полиморфно работать с объектом через общий интерфейс, то разработчик обязан обработать исключение, объявленное в интерфейсе, а если одна из реализаций интерфейса генерирует более общее исключение, то это нарушает полиморфизм. Поэтому такой код даже не скомпилируется.

При этом при переопределении можно вообще не объявлять бросаемые исключения, таким образом сообщив, что все проблемы будут решены в методе:

class PPerson extends Person {
@Override
void hello() {
// some code
}
}

Отсюда следует третий совет: необходимо думать о тех исключениях, которые делегирует метод, если класс может участвовать в наследовании.

Предпочитайте исключения кодам ошибок и boolean флагам-признакам успеха

  1. Исключения более информативны: они позволяют передать сообщение с описанием ошибки
  2. Исключение практически невозможно проигнорировать
  3. Исключение может быть обработано кодом, находящимся выше по стеку, а boolean-флаг или код ошибки необходимо обрабатывать здесь и сейчас

Исключения и статические блоки

Еще интересно поговорить про то, что происходит, если исключение возникает в статическом блоке.

Так вот, такие исключения оборачиваются в java.lang.ExceptionInInitializerError:

public class ExceptionHandling {
static {
throwRuntimeException();
}
private static void throwRuntimeException()  {
throw new NullPointerException();
}
public static void main(String[] args)  {
System.out.println("Hello World");
}
}

Результатом будет падение со следующим стектрейсом:

java.lang.ExceptionInInitializerError Caused by: java.lang.NullPointerException at exception.test.ExceptionHandling.throwRuntimeException(ExceptionHandling.java:13) at exception.test.ExceptionHandling. (ExceptionHandling.java:8)

Многопоточность и исключения

Код в Java потоке выполняется в методе со следующей сигнатурой:

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

Непроверяемые исключения обрабатывать необязательно, однако необработанное исключение, выброшенное из run, завершит работу потока.

Например:

public class ExceptionHandling4 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread() {
@Override
public void run() {
throw new RuntimeException("Testing unhandled exception processing.");
}
};
t.start();
}
}

Результатом выполнения этого кода будет то, что возникшее исключение прервет поток исполнения (interrupt thread):

Exception in threadThread-0java.lang.RuntimeException: Testing unhandled exception processing. at exception.test. ExceptionHandling4$1.run(ExceptionHandling4.java:27)

При использовании нескольких потоков бывают ситуации, когда надо знать, как поток завершился, из-за какого именно исключения. И, разумеется, отреагировать на это.

В таких ситуациях рекомендуется использовать Thread.UncaughtExceptionHandler.

t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e)   {
System.out.println("Handled uncaught exception in thread :" + t + " Exception : " + e);
}
});

И вывод уже будет:

Handled uncaught exception in thread :Thread[Thread-0,5,main] Exception : java.lang.RuntimeException: Testing unhandled exception processing.

Необработанное исключение RuntimeException("Testing unhandled exception processing."), убившее поток, было перехвачено специальным зарегистрированным обработчиком.

Проверяемые исключения и их необходимость

В большинстве языков программирования, таких как C#, Scala, Groovy, Python и т.д., нет такого разделения, как в Java, на проверяемые и непроверяемые исключения.
Почему оно введено в Java было разобрано выше, а вот почему проверяемые исключения недолюбливают разработчики?

Основных причин две, это причины с: версионированием и масштабируемостью.

Представим, что вы, как разработчик библиотеки, объявили некоторый условный метод foo, бросающий исключения A, B и C:

void foo() throws A, B, C;

В следующей версии библиотеки в метод foo добавили функциональности и теперь он бросает еще новое исключение D:

void foo() throws A, B, C, D;

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

И с одной стороны, это правильно, так как в новой версии добавляется еще одно исключение и те, кто использует библиотеку должны отреагировать на все новые исключения. С другой стороны, чаще всего такие исключения будут также проброшены дальше. Все дело в том, что случаев, когда можно обработать специфический тип исключения, например тот же D или A в примере выше, и сделать в обработчике что-то интеллектуальное, можно пересчитать по пальцам одной руки.

Проблема с масштабируемостью начинается тогда, когда происходит вызов не одного, а нескольких API, каждый из которых также несет с собой проверяемые исключения. Представьте, что помимо foo, бросающего A, B, C и D, в методе hello вызывается еще и bar, который также бросает E и T исключения. Как сказано выше, как реагировать чаще всего непонятно, поэтому эти исключения делегируются вызывающему коду, из-за чего объявление метода hello выглядит совсем уж угрожающе:

void hello() throws A, B, C, D, E, T {
try {
foo();
bar();
} finally {
// clear resources if needed
}
}

Все это настолько раздражающе, что чаще всего разработчики просто объявляют наиболее общее исключение в throws:

void hello() throws Exception {
try {
foo();
bar();
} finally {
// clear resources if needed
}
}

А в таком случае это все равно, что сказать «метод может выбросить исключение» — это настолько общие и абстрактные слова, что смысла в throws Exception практически нет.

Также есть еще одна проблема с проверяемыми исключениями. Это то, что с проверяемыми исключениями крайне неудобно работать в lambda-ах и stream-ах:

// compilation error
Lists.newArrayList("a", "asg").stream().map(e -> {throw new Exception();});

Так как с Java 8 использование lambda и stream-ов распространенная практика, то накладываемые ограничения вызовут дополнительные трудности при использовании проверяемых исключений.

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

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

В своей работе я стараюсь чаще использовать непроверяемые исключения, а проверяемые оборачивать в unchecked аналоги, как, например, java.io.IOException и java.io.UncheckedIOException.

Заключение

Иерархия исключений в Java.

Exception Hierarchy

Исключения делятся на два типа: непроверяемые(unchecked) и проверяемые(checked). Проверяемые исключения — это исключения, которые проверяются на этапе компиляции, мы обязаны на них отреагировать.

Проверяемые исключения в Java используются тогда, когда разработчик никак не может предотвратить их возникновение. Причину возникновения java.lang.RuntimeException можно проверить и устранить заранее, например, проверить ссылку на null перед вызовом метода, на объекте по ссылке. А вот с причинами проверяемых исключений так сделать не получится, так как ошибка при чтении файла может возникнуть непосредственно в момент чтения, потому что другая программа его удалила. Соответственно, при чтении файла требуется обрабатывать java.io.IOException, который является потомком java.lang.Exception.

Допускается создание собственных исключений, признак проверяемости или непроверяемости наследуется от родителя. Исключения — это такие же классы, со своим поведением и состоянием, поэтому при наследовании вполне допускается добавить дополнительное поведение или свойства классу.

Обработка исключений происходит с помощью конструкции try/catch/finally. Один блок try может иметь несколько catch блоков. В таком случае будет выполняться первый подходящий блок.

Помните, что try блок не транзакционен, все ресурсы, занятые в try ДО исключения остаются в памяти. Их надо освобождать и очищать вручную.
Если вы используете Java версии 7 и выше, то отдавайте предпочтение конструкции try-with-resources.

Основное правило:

На исключения можно реагировать, их обработку можно делегировать, но ни в коем случае нельзя их игнорировать.

Определить когда надо реагировать, а когда делегировать проще простого. Задайте вопрос: «Знаю ли я как реагировать на это исключение?».
Если ответ «да, знаю», то реагируйте, пишите обработчик и код, отвечающий за эту реакцию, если не знаете что делать с исключением, то делегируйте вызывающему коду.

Помните, что перехват java.lang.Error стоит делать только если вы точно знаете, что делаете. Восстановление после таких ошибок не всегда возможно и почти всегда нетривиально.
Не забывайте, что большинство ошибок java.lang.RuntimeException и его потомков можно избежать.

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

Представьте себе, что существуют пять причин, по которым может быть выброшено исключение, и во всех пяти случаях бросается java.lang.Exception. Вы же спятите разбираться, чем именно это исключение вызвано.

(c) Евгений Матюшкин.

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

Постарайтесь не создавать ‘универсальных’ обработчиков, так как это чревато трудноуловимыми ошибками.

Если исключение можно не генерировать, то лучше так и сделать. Не пренебрегайте проверками.

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

Помните:

In Java you can ignore exceptions, but you have to willfully do it. You can’t accidentally say, «I don’t care.» You have to explicitly say, «I don’t care.»

(c) James Gosling.

Для закрепления материала рекомендую ознакомиться с ссылками ниже и этим материалом.

Полезные ссылки

  1. Книга С. Стелтинг ‘Java без сбоев: обработка исключений, тестирование, отладка’
  2. Oracle Java Tutorials
  3. Лекция Технострим Исключения
  4. Лекция OTUS Исключения в Java
  5. Лекция Ивана Пономарёва по исключениям
  6. Заметка Евгения Матюшкина про Исключения
  7. Failure and Exceptions by James Gosling
  8. The Trouble with Checked Exceptions by Bill Venners with Bruce Eckel
  9. Никто не умеет обрабатывать ошибки
  10. Исключения и обобщенные типы в Java
  11. Вопросы для закрепления
1с реструктуризация server selected protocol TLS10 is not accepted by client preferences ☑ 0

RoRu

27.01.22

12:04

есть большая база, 1с рекомендует выставить при обновлении параметр реструктуризации оптимизированный

выставляю – получаю ошибку.

а как просто посмотреть кол-во проводок в БП , может и старым методом пройдёт , там от 100 000 пишут новый запускать ?

админы сторонние , ошибку им передал, но и тут спрошу, может кто в курсе

В процессе обновления конфигурации базы данных при работе оптимизированного механизма обновления произошла критическая ошибка

по причине:

В процессе обновления конфигурации базы данных при работе оптимизированного механизма обновления произошла критическая ошибка

по причине:

Критическая ошибка работы Java-процесса.

Путь к Java: C:\Program Files\Java\jre1.8.0_321\bin\java.exe

Действие: prepare

Process ID: 5340

Код возврата: 1

Ошибка: Exception in thread “main” com._1c.dmf.v8.cli.ApplicationException: com.microsoft.sqlserver.jdbc.SQLServerException: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: “The server selected protocol version TLS10 is not accepted by client preferences [TLS12]”. ClientConnectionId:de2212d4-8a77-49f8-8f42-0bfd41a57046

    at com._1c.dmf.v8.cli.jdbc.mssql.MsSqlDataSourceFactory.getYearOffset(MsSqlDataSourceFactory.java:105)

    at com._1c.dmf.v8.cli.jdbc.mssql.MsSqlDataSourceFactory.create(MsSqlDataSourceFactory.java:51)

    at com._1c.dmf.v8.cli.Migration.run(Migration.java:81)

    at com._1c.dmf.v8.cli.Migration.main(Migration.java:65)

Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: “The server selected protocol version TLS10 is not accepted by client preferences [TLS12]”. ClientConnectionId:de2212d4-8a77-49f8-8f42-0bfd41a57046

    at com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:2435)

    at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1816)

    at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:2022)

    at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:1687)

    at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:1528)

    at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:866)

    at com.microsoft.sqlserver.jdbc.SQLServerDataSource.getConnectionInternal(SQLServerDataSource.java:968)

    at com.microsoft.sqlserver.jdbc.SQLServerDataSource.getConnection(SQLServerDataSource.java:69)

    at com._1c.dmf.v8.cli.jdbc.V8DataSource.getConnection(V8DataSource.java:36)

    at com._1c.dmf.v8.cli.jdbc.mssql.MsSqlDataSourceFactory.getYearOffset(MsSqlDataSourceFactory.java:86)

    … 3 more

Caused by: javax.net.ssl.SSLHandshakeException: The server selected protocol version TLS10 is not accepted by client preferences [TLS12]

    at sun.security.ssl.Alert.createSSLException(Unknown Source)

    at sun.security.ssl.Alert.createSSLException(Unknown Source)

    at sun.security.ssl.TransportContext.fatal(Unknown Source)

    at sun.security.ssl.TransportContext.fatal(Unknown Source)

    at sun.security.ssl.TransportContext.fatal(Unknown Source)

    at sun.security.ssl.ServerHello$ServerHelloConsumer.onServerHello(Unknown Source)

    at sun.security.ssl.ServerHello$ServerHelloConsumer.consume(Unknown Source)

    at sun.security.ssl.SSLHandshake.consume(Unknown Source)

    at sun.security.ssl.HandshakeContext.dispatch(Unknown Source)

    at sun.security.ssl.HandshakeContext.dispatch(Unknown Source)

    at sun.security.ssl.TransportContext.dispatch(Unknown Source)

    at sun.security.ssl.SSLTransport.decode(Unknown Source)

    at sun.security.ssl.SSLSocketImpl.decode(Unknown Source)

    at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(Unknown Source)

    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)

    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)

    at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1753)

    … 11 more

1

palsergeich

27.01.22

12:11

2

МихаилМ

27.01.22

12:37

(1) не осилит.

3

Ёпрст

27.01.22

13:03

(0) короче, нужно в java.security найти строки с tlsv1

4

Ёпрст

27.01.22

13:03

и удалить из алгортима

5

Ёпрст

27.01.22

13:04

6

Ёпрст

27.01.22

13:05

открыть java.security, найти jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA,  и в ней удалить TLSv1, TLSv1.1

7

Ёпрст

27.01.22

13:05

усё.

8

RoRu

27.01.22

14:28

(2) с чего бы ?

зы у меня прав нет, админам передал

Епрст- спасибо, но вроде всё понятно там

9

МихаилМ

27.01.22

14:36

(8) т.к. не владеет минимальным базовым навыком пользования поисковыми сервисами интернет.

т.е. проф. непригодны

10

arsik

27.01.22

14:53

Самое простое удалить эту джаву и установить из дистрибутива с сайта 1С

11

RoRu

27.01.22

15:10

(10) спасибо !

12

Ёпрст

27.01.22

15:12

(0)

>>>>а как просто посмотреть кол-во проводок в БП

какой формат базы, для начала..файловая что ле ?

13

RoRu

27.01.22

15:14

(12)

sql

вопрос был средствами 1с

зы я консультант

14

Ёпрст

27.01.22

15:14

(13) ИР открой да гляди.

Перед реструктуризацией V2 прибей все итоги V2, тогда даже не заметишь, как и пройдёт.

15

Ёпрст

27.01.22

15:15

* прибей все итоги РБ

16

Ёпрст

27.01.22

15:16

и да, 20 релиз я бы не ставил, лучше 18

17

RoRu

27.01.22

15:18

(16) да, это понятно, везде 18 ставим

18

RoRu

27.01.22

15:19

(14) точно

19

RoRu

27.01.22

15:51

(10) а как узнать какую из 4ёх на сайте ?

20

arsik

27.01.22

17:49

(19) Достаточно JRE, JDK нужно для разработчиков. 11 или 8 – У вас сейчас стоит 8, но я бы выбрал 11.

21

RoRu

27.01.22

17:55

(20) а в принципе любая должна подойти, чтобы реструктуризация по новому на sql взлетела? правильно я понимаю ?

или там возможны заморочки?

22

arsik

27.01.22

19:07

(21) Да

23

Dunemaster

27.01.22

23:28

Ваша проблема вызвана тем, что в новых сборках Java (JDK/JRE) старый протокол TLS 1.0 запрещен как небезопасный, а MS SQL Server пытается использовать именно ее

Какие могут быть решения:

1) Использовать более старую версию Java (не релиз, а именно версию внутри врупного релиза т.е какую более раннюю версию Java 8)

2) Изменить умолчания Java, как описано в (6)

3) Обновить MS SQL Server, чтобы он использовал более современные версии TLS

У Microsoft есть подробная инструкция

24

Dunemaster

27.01.22

23:28

25

RoRu

28.01.22

00:12

в рабочее время отгрузки, так что я могу только вечером делать

(22) установил с сайта 1с 11 версию , сначала не видело яву, прописал в кфг

стало ругаться на  TLSv1, TLSv1.1

прописал в секюрити явы – написало нету классов в 11 яве

поставил 8ую, снова прописал путь в кфг и поправив секьюрити – взлетело

(24) я не особо в теме, а админы  особого желания разбираться  не изъявляли, ну и имхо это сложнее , чем исправить секьюрити  

всем спасибо !

26

МихаилМ

28.01.22

00:30

(25) если админы не понимают устно ,то переходите на письменно. это азы правил корпоративного выживания. за одно и свою персону прикроете.

Нам всем знакомо, как долго может идти обновление: это может занимать несколько часов, а в некоторых случаях – даже
несколько дней.

Однако, его можно заметно ускорить. А для этого нужно немного погрузиться в детали и поговорить о реструктуризации 🙂

Когда в 1С изменяются метаданные (добавляются документы, реквизиты, индексы), происходит изменение структуры таблиц.

При запуске обновления создается полная копия таблицы, включая индексы – уже с новой структурой. Этот процесс называется реструктуризацией. Разумеется, это все занимает довольно заметное время.

Для случаев, когда объемы данных небольшие, это не так чувствительно.

Но реструктуризация больших баз, в которых содержатся таблицы с десятками миллионов строк, может затянуться на несколько часов или даже дней. Потеря такого количества времени – это уже весьма болезненно.

Еще в платформе 8.3.11 появился механизм, который помогает ускорить реструктуризацию в разы, а в некоторых случаях – на порядки.

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

Сегодняшнее видео закрывает этот вопрос:

  • Объясняем, чем механизм, который появился в 8.3.11, отличается от стандартного способа реструктуризации
  • Показываем, как настроить и использовать новый механизм
  • Демонстрируем его преимущества и рассказываем о его недостатках
  • Объясняем, кому необходим этот механизм, а кому переходить на него не стоит.

Если Вы недовольны тем, с какой скоростью проходит реструктуризация в ваших базах, это видео обязательно к просмотру.

Но даже если Вы работаете в маленькой компании и с этой проблемой еще не столкнулись – рекомендуем все-таки найти 17 минут и посмотреть его. Если завтра Вы поменяете работу и столкнетесь с такой проблемой – не придется волноваться из-за того, что Вы не в курсе таких нюансов.

Ключевые моменты видео:

  • 00:00 – Постановка задачи
  • 00:28 – Старый способ реструктуризации и его недостатки
  • 01:50 – Новый способ реструктуризации
  • 02:17 – Плюсы нового способа
  • 03:04 – Установка Java на сервер 1С
  • 04:18 – Настройка файла conf.cfg на клиенте
  • 05:40 – Демонстрация работы старого механизма
  • 07:36 – Демонстрация работы нового механизма
  • 08:58 – Особенности использования нового механизма
  • 09:10 – Включение протокола TCP/IP для СУБД
  • 10:52 – Проверка сторонних индексов
  • 13:20 – Настройка параметра MAXDOP в MS SQL
  • 16:36 – Итоги

video

После курса Вы сможете:

  • Оценивать состояние системы в любой момент времени
  • Быстро находить причины замедления в программном коде – и сразу писать его так, чтобы замедления в будущем не было
  • Отслеживать динамику производительности за определенный период
  • Устранять ожидания на блокировках и решать проблемы со взаимоблокировками

Для кого этот курс

Вам нужен этот курс, если Вы хотите:

  • Писать код, за который не стыдно – в нестабильное время особенно важно быть в компании на хорошем счету
  • Быть востребованным специалистом – на каждом втором собеседовании спрашивают про умение оптимизировать 1С
  • Не терять клиентов из-за того, что «ваша 1С тормозит, а вы ничего не делаете» – это и раньше было нехорошо, а теперь и вовсе непозволительная роскошь.

<?php // Полная загрузка сервисных книжек, создан 2023-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

Related Posts

  • Восстановление последовательности документов при закрытии месяца в Бухгалтерия 3.0 не завершается
  • Заполнение табличных частейЗаполнение табличных частей
  • Формирование сводных актов выполненных работ
  • Ввод поступления в переработку на основании передачи сырья (между организациями)
  • Конспект по установке сервера 1С на linuxКонспект по установке сервера 1С на linux
  • Получение имени компьютера и его IP локально и в терминале

46 Comments

  1. (1) да, весьма в тему, спасибо!

    Reply

  2. Буду тестировать скоро отключение режима совместимости 8.2))) БД почти 3 ТБ.

    Reply

  3. Двойственные чувства.

    С одной стороны слава тебе Господи, наконец-то 1С сподобилась взяться за то, что куча народа ждало еще со времён 7.7. С другой стороны тут и Java, тут и Powershell… А сплясать в водолазном костюме в гамаке не надо?

    Reply

  4. (4) аналогичные чувства… только обрадоваться хотел, но остался вопрос, почему нельзя сделать это всё прямо из платформы, по кнопке «сделать всё хорошо»?

    Reply

  5. (4) Java — это отголоски наработок по платформе 1C 8.4. Развитие этой версии идет медленно и новостей давно не слышно, но ее наработки постепенно появляются в 8.3. На Java никто писать не заставляет, а представить машину без JRE сейчас сложно. И судя по всему с Java придется дружить всё больше — EDT, сервер взаимодействия и т.д.

    Powershell для примера же приведен. Там кроме команды запуска 1С с параметрами «UpdateDBCfg -Server -v2» и нет ничего, одна консольная команда. Не внешнюю же обработку для выполнения одной консольной команды писать…

    Reply

  6. Я один раз пробовал.

    Мне вывело сообщение ошибка и на какой то внутренний модуль.

    Гугл сказал что ничего не светит. я сказал ок и по старому за 6 часов обновился.

    Обидно конечно.

    Reply

  7. Интересно что за данные в базе на 1тб.

    Reply

  8. (6)

    Там кроме команды запуска 1С с параметрами «UpdateDBCfg -Server -v2» и нет ничего

    CMD не подойдёт?

    Reply

  9. (8)скорее всего продажи, чеки, заказы на перемещение / перемещения на магазины.

    У нас база 3 Тб

    Reply

  10. (8)Размер базы обычной небольшой торговой сети, может быть еще с небольшим производством…

    Reply

  11. Можно и cmd. Друзья, конечно это не одна кнопка «сделать всё хорошо», но уже существенный задел. База — склад, продажи, логистика. Плюс у нас ещё и РИБ. Механизм обновления активно используем, все работает… На ИТС информации мало, поэтому посчитал нужным поделиться опытом и отчитаться об успехе) в дальнейшем неплохо было бы иметь возможность обновляться пакетно с возможностью логгировать ход обновления

    Reply

  12. (12)пока логирование обновления можно наблюдать на стороне базы данных

    Reply

  13. У конфигурации режим совместимости был 8.3.11? Или ниже?

    Reply

  14. (14) режим совместимости был выключен. Но думаю, в режиме совместимости 8.3.11 должно отработать

    Reply

  15. (15) значит как и завялено при режиме совместимости 8.3.10 все будет по старому!

    Reply

  16. О даааа!!!!! Это случилось! В 1С выучили Alter Table!

    Reply

  17. Малину портит только » На сервере 1С обязательно должен быть установлен runtime Java 8″. Вопрос «зачем так» наверное риторический…

    Reply

  18. (18) весь «интеллект» умных скриптов T-SQL написан на Java, в недрах платформы, насколько я понял ))

    Reply

  19. (19) т.е. можно в принципе написать левый скрипт на Java, который реструктуризует базу под новую конфигурацию и зальет туда измененный cf с гитхаба или с какого нибудь каталога?

    И все будет работать?

    Reply

  20. (19) в недрах платформы Java нет, иначе мы бы это уже «почувствовали».

    Пока надеюсь что и не будет.

    Reply

  21. (20) можно декомпильнуть то что написано, подправить и юзать как хочется теперь 🙂

    Reply

  22. (23) на каждое добавление булева не надекомпилируешься. Но сама идея о неразрывном совмещении данных в базе и их интерфейса достаточно спорная.

    При том, что на все итоги и индексы, целостность которых якобы гарантирует платформа, существуют процедуры SQL, выполняющие пересчеты.

    Reply

  23. (22) ну как-то же она тексты скриптов собирает, в зависимости от выполненных действий в конфигураторе

    Reply

  24. (26) мы бы тоже хотели знать как и почему alter возник только сейчас. Исторически сложилось, что реструктуризация выполнялась таким образом в DBF. Сначала все измененные файлы складывались в папку NewStru, затем копировались вместо находящихся в базе. Почти цитирую старый мануал: при возникновении сбоя на первом этапе файлы в базе будут первоначальных вариантов и никакие данные не будут утеряны.

    При возникновении сбоя на втором этапе часть данных в базе может стать некорректной, но всегда есть возможность скопировать файлы из NewStru и завершить процесс реструктуризации вручную. Исходили из положения что бакап и изменение структуры в процессе работы с DBF по-горячему сделать невозможно, а программист, обслуживающий конфигурацию не полезет в dbf и работу платформы, но точно знает основы работы с файлами в файловом менеджере.

    В SQL есть возможность добавить колонку в таблицу в процессе работы. Немонопольно. Это не проблема для SQL, это проблема конфигуратора, который не умеет работать одновременно с разными версиями данных (до и после) какой то реструктуризации.

    Reply

  25. (7)

    Вот такое у меня сейчас. Ковыряемся. Ради спортивного интереса хочу докопаться до причин.

    В процессе обновления конфигурации базы данных при работе оптимизированного механизма обновления произошла критическая ошибка

    по причине:

    Критическая ошибка работы Java-процесса.

    Путь к Java: C:Program FilesJavajre1.8.0_181injava.exe

    Действие: prepare

    Process ID: 22296

    Код возврата: 1

    Ошибка: Exception in thread «main» java.lang.IllegalStateException: Duplicate key ae4a0c5e-f97b-4cf4-96d8-c040bf8e222b

    at java.util.stream.Collectors.lambda$throwingMerger$0(Unknown Source)

    at java.util.HashMap.merge(Unknown Source)

    at java.util.stream.Collectors.lambda$toMap$58(Unknown Source)

    at java.util.stream.ReduceOps$3ReducingSink.accept(Unknown Source)

    at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(Unknown Source)

    at java.util.stream.AbstractPipeline.copyInto(Unknown Source)

    at java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)

    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(Unknown Source)

    at java.util.stream.AbstractPipeline.evaluate(Unknown Source)

    at java.util.stream.ReferencePipeline.collect(Unknown Source)

    at com._1c.dmf.v8.converters.parameters.documentjournal.GraphContent.<init>(GraphContent.java:24)

    at com._1c.dmf.v8.cli.modelparsing.ConfigurationModelParser.deserializeGraphContent(ConfigurationModelParser.java:352)

    at com._1c.dmf.v8.cli.modelparsing.ConfigurationModelParser.deserializeValue(ConfigurationModelParser.java:208)

    at com._1c.dmf.v8.cli.modelparsing.ConfigurationModelParser.deserializeParameter(ConfigurationModelParser.java:172)

    at com._1c.dmf.v8.cli.modelparsing.ConfigurationModelParser.deserializeAttributeParameter(ConfigurationModelParser.java:155)

    at com._1c.dmf.v8.cli.modelparsing.ConfigurationModelParser.deserializeEntityParameters(ConfigurationModelParser.java:139)

    at com._1c.dmf.v8.cli.modelparsing.ConfigurationModelParser.deserializeParameters(ConfigurationModelParser.java:112)

    at com._1c.dmf.v8.cli.modelparsing.ConfigurationModelParser.parse(ConfigurationModelParser.java:92)

    at com._1c.dmf.v8.internal.integration.Arguments.getOldModel(Arguments.java:84)

    at com._1c.dmf.v8.internal.integration.DmfService.prepareMigration(DmfService.java:64)

    at com._1c.dmf.v8.cli.Migration.run(Migration.java:90)

    at com._1c.dmf.v8.cli.Migration.main(Migration.java:65)

    Reply

  26. (28)

    at java.util.HashMap.merge(Unknown Source)

    Да что то очень похожее.

    Причем все базы кроме нужной реструктурировались новым методом нормально.

    Но там было не к спеху, и я просто сделал по старинке.

    Изменений очень много было, может в этом была проблема?

    Reply

  27. (28) поставь Яву не 181, а 171 или младше

    Reply

  28. (21) я на java драйвера для фискальных регистраторов пишу, очень удобно, т.к. один код работает под виндой, линуксом и андроидом. Что я делаю не так? С++ я тоже умею.

    Reply

  29. (31) драйвера или обёртки для готовых dllso ?

    Reply

  30. (32) библиотеки работы с com/usb готовые, драйвера мои что-то типа….

    @Override

    public ByteBuffer getCommand() {

    ByteBuffer data = ByteBuffer.allocate(12 + cashier.length() + cashierFiscalId.length());

    data.order(ByteOrder.LITTLE_ENDIAN);

    data.putShort((short) 2); // отчет об открытии смены

    data.putShort((short) (4 + cashier.length() + 4 + cashierFiscalId.length()));

    data.putShort((short) 1021);

    data.putShort((short) cashier.length());

    data.put(cashier.getBytes(Charset.forName(«IBM866»)));

    data.putShort((short) 1203);

    data.putShort((short) cashierFiscalId.length());

    data.put(cashierFiscalId.getBytes(Charset.forName(«IBM866»)));

    setData(data);

    return super.getCommand();

    }

    Reply

  31. (0) Спасибо за интересный материал! Не подскажите, режим совместимости с 8.2.13 возможно заставить работать этот механизм?

    Reply

  32. (34) к сожалению, нет. Вам придется прибегать к другим методам… О том, как добавлять колонки и индексы в большие таблицы БД — куча статей есть на ИС, в том числе и у меня (не реклама)

    Reply

  33. Надо добавить, что для клиент — серверного варианта базы нужно перезапустить службу сервера 1С

    У меня возникла ошибка

    В процессе обновления конфигурации базы данных при работе механизма реструктуризации второй версии произошла критическая ошибка

    по причине:

    При работе механизма реструктуризации второй версии возникла ошибка. Код возврата: 1. Операция: execute.

    Версия платформы 8.3.13.1513

    Reply

  34. (0) молодцы! ждем вьюхи

    Reply

  35. (21) Ну при всей моей нелюбви к Джаве, я бы все-таки не стал называть ее мусором 🙂 Тот же Apache Kafka на ней написан и шустр до безобразия.

    Reply

  36. (2) и еще в догонку по теме «для тех кто тюнингует 1С+MS SQL» http://v8.1c.ru/predpriyatie/questions_licence.htm#lrvs1cpp

    это к последнему апдейту

    ВАЖНО: Если обновление по v2 падает с ошибкой — одна из причин может быть в том, что в вашей БД есть индексы, отличные от стандартных платформенных (добавленные вручную) — их необходимо физически удалить (именно удалить, а не отключить) перед запуском обновления.

    Reply

  37. А, говорят, Java теперь платная, Oracle денег просит за её использование

    не в домашнем применении.

    Reply

  38. (4) я думал только у меня такое ощущение)

    Reply

  39. почти типовая УПП…

    В процессе обновления конфигурации базы данных при работе оптимизированного механизма обновления произошла критическая ошибка

    по причине:

    Критическая ошибка работы Java-процесса.

    Путь к Java: C:Program Files (x86)Javajre1.8.0_221injava.exe

    Действие: prepare

    Process ID: 2660

    Код возврата: 1

    Ошибка: Exception in thread «main» java.lang.OutOfMemoryError: Java heap space

    Reply

  40. Эта проблема решилась добавлением опции JavaOpts=-Xmx2048m в conf.cfg, но теперь ошибка без расшифровки

    Критическая ошибка работы Java-процесса.

    Путь к Java: C:Program Files (x86)Javajre1.8.0_221injava.exe

    Действие: prepare

    Process ID: 3392

    Код возврата: 1

    Ошибка:

    Reply

  41. повышение режима совместимости УПП до 8.3.1 результатов не дало. Видать сырая еще опция

    Reply

  42. (44) механизм работает с версии 8.3.11. Совместимость должна быть не ниже этой версии

    Reply

  43. (45)

    Неверно. У меня в режиме совместимости 8.3.6 отрабатывает.

    Reply

  44. (1) Ирония в том, что в старом механизме реструктуризации указание MAXDOP=0 используется по умолчанию, она добавлена в качестве опции в запросе на создание индекса.

    А вот в новом механизме, который описан в данной статье, разработчики почему-то забыли эту опцию включить в запрос и если в настройках сервера MAXDOP равен 1, то реструктуризация будет медленнее чем хотелось бы . Возможно следует в статье 4-м пунктом добавить, что включение на сервере MAXDOP=0 на время реструктуризации, дополнительно ускорит этот процесс.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Critical error: wait for JVM process failed

В мире программирования, особенно при работе с Java-приложениями, часто возникают различные ошибки. Одной из таких ошибок является “Critical error: wait for JVM process failed”. В этой статье мы рассмотрим причины возникновения данной ошибки, а также предложим возможные решения.

Перед тем, как перейти к причинам и решениям, давайте сначала разберемся, что означает данная ошибка. Как правило, “Critical error: wait for JVM process failed” появляется при запуске или остановке Java-приложения. Ошибка указывает на проблему взаимодействия с процессом JVM (Java Virtual Machine). JVM играет ключевую роль в выполнении Java-приложений, и его неправильная работа может вызвать подобную ошибку.

Теперь перейдем к возможным причинам появления данной ошибки:

1. Недостаточно оперативной памяти: JVM требуется определенное количество оперативной памяти для правильной работы. Если доступное количество памяти недостаточно для JVM, это может привести к ошибке “Critical error: wait for JVM process failed”. Рекомендуется увеличить выделенное количество оперативной памяти для Java-приложения.

2. Поврежденный или неправильно установленный JDK (Java Development Kit): Если JDK установлен неправильно или некорректно настроен, это может стать причиной появления ошибки. В этом случае, следует проверить правильность установки и настроек JDK.

3. Конфликты между версиями JVM: Возможно, на вашем компьютере установлено несколько версий JVM. Это может привести к конфликтам и вызвать ошибку “Critical error: wait for JVM process failed”. Рекомендуется удалить все старые или неиспользуемые версии JVM, оставив только одну рабочую версию.

4. Неправильно настроенное окружение: Если окружение вашей системы неправильно настроено, это может привести к проблемам в работе JVM и вызвать ошибку. Рекомендуется проверить настройки окружения, такие как переменные среды, и убедиться, что они настроены правильно.

Теперь перейдем к возможным решениям для исправления ошибки “Critical error: wait for JVM process failed”:

1. Увеличение выделенной оперативной памяти: Вы можете увеличить выделенное количество оперативной памяти для JVM, добавив опцию “-Xmx” в командной строке запуска приложения. Например, “java -Xmx1024m MyApp” устанавливает максимальный объем памяти в 1024 мегабайта.

2. Переустановка и настройка JDK: Если проблема связана с неправильно установленным JDK, рекомендуется его удалить и переустановить. Важно также проверить настройки окружения и правильность указания пути к JDK.

3. Удаление лишних версий JVM: Если на вашем компьютере установлено несколько версий JVM, удалите все старые или неиспользуемые версии. Оставьте только одну версию, которая должна быть совместима с вашим приложением.

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

В заключение, ошибка “Critical error: wait for JVM process failed” может быть вызвана несколькими причинами, включая недостаток памяти, проблемы с JDK и конфликты между версиями JVM. Для исправления проблемы рекомендуется увеличить выделенную оперативную память, переустановить и настроить JDK, удалить лишние версии JVM и проверить настройки окружения. Устранение проблемы может потребовать некоторого технического опыта, поэтому, при необходимости, обратитесь за помощью к опытному программисту или специалисту по Java-разработке.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *