I’ve updated java from 8 to 9-ea and gradle from 2.13 to 3.4.1. Below is the gradle --version
output.
------------------------------------------------------------
Gradle 3.4.1
------------------------------------------------------------
Build time: 2017-03-03 19:45:41 UTC
Revision: 9eb76efdd3d034dc506c719dac2955efb5ff9a93
Groovy: 2.4.7
Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM: 9-ea (Oracle Corporation 9-ea+158)
OS: Linux 4.8.0-36-generic amd64
while compiling below error is encountered:
FAILURE: Build failed with an exception.
* What went wrong:
java.lang.ExceptionInInitializerError (no error message)
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
and the output of gradle --stacktrace
is below:
java.lang.ExceptionInInitializerError
at org.gradle.initialization.DefaultClassLoaderRegistry.restrictTo(DefaultClassLoaderRegistry.java:40)
at org.gradle.initialization.DefaultClassLoaderRegistry.restrictToGradleApi(DefaultClassLoaderRegistry.java:36)
at org.gradle.initialization.DefaultClassLoaderRegistry.<init>(DefaultClassLoaderRegistry.java:30)
at org.gradle.internal.service.scopes.GlobalScopeServices.createClassLoaderRegistry(GlobalScopeServices.java:213)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:547)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
at org.gradle.internal.service.DefaultServiceRegistry.invoke(DefaultServiceRegistry.java:462)
at org.gradle.internal.service.DefaultServiceRegistry.access$1200(DefaultServiceRegistry.java:84)
at org.gradle.internal.service.DefaultServiceRegistry$FactoryMethodService.invokeMethod(DefaultServiceRegistry.java:805)
at org.gradle.internal.service.DefaultServiceRegistry$FactoryService.create(DefaultServiceRegistry.java:761)
at org.gradle.internal.service.DefaultServiceRegistry$ManagedObjectProvider.getInstance(DefaultServiceRegistry.java:598)
at org.gradle.internal.service.DefaultServiceRegistry$SingletonService.get(DefaultServiceRegistry.java:643)
at org.gradle.internal.service.DefaultServiceRegistry.applyConfigureMethod(DefaultServiceRegistry.java:253)
at org.gradle.internal.service.DefaultServiceRegistry.findProviderMethods(DefaultServiceRegistry.java:214)
at org.gradle.internal.service.DefaultServiceRegistry.addProvider(DefaultServiceRegistry.java:352)
at org.gradle.internal.service.ServiceRegistryBuilder.build(ServiceRegistryBuilder.java:52)
at org.gradle.launcher.cli.BuildActionsFactory.createGlobalClientServices(BuildActionsFactory.java:148)
at org.gradle.launcher.cli.BuildActionsFactory.runBuildWithDaemon(BuildActionsFactory.java:108)
at org.gradle.launcher.cli.BuildActionsFactory.createAction(BuildActionsFactory.java:83)
at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.createAction(CommandLineActionFactory.java:249)
at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:239)
at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:217)
at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:33)
at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24)
at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)
at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)
at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:210)
at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:174)
at org.gradle.launcher.Main.doAction(Main.java:33)
at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:547)
at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:60)
at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:37)
at org.gradle.launcher.GradleMain.main(GradleMain.java:23)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected java.lang.Package[] java.lang.ClassLoader.getPackages() accessible: module java.base does not "opens java.lang" to unnamed module @6c7a164b
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:335)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:278)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:196)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:190)
at org.gradle.internal.reflect.JavaMethod.<init>(JavaMethod.java:42)
at org.gradle.internal.reflect.JavaMethod.<init>(JavaMethod.java:32)
at org.gradle.internal.reflect.JavaMethod.<init>(JavaMethod.java:36)
at org.gradle.internal.reflect.JavaReflectionUtil.method(JavaReflectionUtil.java:223)
at org.gradle.internal.classloader.FilteringClassLoader.<clinit>(FilteringClassLoader.java:49)
... 40 more
when I set
export GRADLE_OPTS="-Dorg.gradle.jvmargs=--add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED"
as suggested at different places, issue remains the same.
Kindly help me out in resolving the issue.
UPDATE:
Changed GRADLE_OPTS
to (wrapped)
export GRADLE_OPTS="-Dorg.gradle.jvmargs=
--add-opens java.lang=ALL-UNNAMED
--add-opens java.util=ALL-UNNAMED
--add-opens java.io=ALL-UNNAMED"
Got the following error:
Error: Could not find or load main class java.lang=ALL-UNNAMED
Caused by: java.lang.ClassNotFoundException: java.lang=ALL-UNNAMED
Содержание
- Студия готового дизайна GS studio
- Login
- Системы сборки. Maven
- Системы сборки. Gradle
- Тестирование REST-контейнеров
- Заключение и спасительный флаг
- How to Handle the Exception In Initializer Runtime Error in Java
- Introduction to Runtime Errors & Exceptions
- ExceptionInInitializerError Error: What, Why & How?
- How to handle the ExceptionInInitializerError Error
Студия готового дизайна GS studio
Login
В конце мая я выступал на JEEConf 2017, где рассказывал об эффективности и производительности Java библиотек и фреймворков. Любое упоминание о производительности должно ссылаться на результаты измерений, что я и сделал во время доклада. Но я решил пойти дальше и протестировать один и тот же код на двух версиях — Java 8 и Java 9.
Хоть Java 9 и выходит только в июле (уже в сентябре), но она уже перешла в стадию Release Candidate, то есть никаких новых фич больше не будет и все критические баги должны быть исправлены. Я начал пользоваться Java 8 за 5 месяцев до релиза и никаких особых проблем при этом не испытал. В то же время главная фича новой версии — модуляризация (проект Jigsaw) привела к многочисленным изменениям внутри самой JDK. Хорошо было бы протестировать библиотеки на новой версии. В сети есть много статей и видео-докладов на тему проектирования модулей. Но сначала нужно проверить, а будет ли работать существующее приложение, и если будет, то как отразится миграция на скорости работы нашей системы. Не секрет, что многие компании остаются на старых версиях (Java 5 — 7) частично из-за боязни новых ошибок и проблем в производительности. Если же приложение работать не будет, насколько просто это починить?
Поэтому я призываю всех установить JDK 9 и протестировать свое приложение. Разумеется, вы можете и дальше использовать текущую версию Java, но прогресс не стоит на месте. Через пару лет выйдет Java 10, а с ней возможно и свойства, и value types, и все равно придется использовать модульность. Тем более что современные IDE (IntelliJ IDEA) уже поддерживают все фичи Java 9.
Системы сборки. Maven
Сборка проекта — это процесс, который проходит постоянно в течение рабочего дня как на компьютере разработчика, так и на CI сервере. Поэтому здесь требуется максимальное быстродействие. Для тестирования сборки я выбрал проект, который я разрабатываю в рамках книги «Разработка Java приложений», тем более что он поддерживает и Maven, и Gradle. Проект постоянно обновляется, поэтому версии зависимостей в нем года либо конца года. Вы сами можете скачать проект и протестировать на своей машине.
Поддерживают ли Maven/Gradle Java 9? Это интересный вопрос, тем более что их модель зависимостей чем-то похожа и даже является конкурентом JDK 9.
Итак, я установил JDK Early Access preview build 171 на Windows систему. Результат запуска команды «java -version»:
Начнем с Maven. Для тестирования я выбрал последнюю версию — 3.5.0. Сам Maven запускается без проблем, выдает корректную версию JDK:
Теперь запустим сборку проекта: mvn clean install. Сборка падает на этапе запуска тестов с ошибкой:
Почему-то стандартный класс JAXBException больше не находится. Дело в том, что все, связанное с JAXB, перенесено Java в модуль java.xml.bind, который автоматически не добавляется в modulepath при запуске JVM, потому что не входит в дефолтный модуль java . se. Как выйти из этого положения? Либо явно указать этот модуль для запуска JVM, либо агрегатный модуль java . se . ee, куда входит все, что связано с Java EE API. Разумеется, добавить агрегатный модуль удобнее, чем каждый модуль по отдельности. Поэтому добавляем переменную окружения MAVEN_OPTS (если у вас ее еще нет), и присваиваем ей значение «—add-modules java . se . ee».
Однако ошибка не исчезает. Все дело в том, что тесты запускает Maven Surfire плагин, который стартует новый JVM процесс. Для того, чтобы указать новые модули, нужно добавить Surfire плагин в главный pom.xml и передать параметры там:
Перезапускаем сборку и получаем новое исключение:
Эта проблема не имеет очевидного решения, потому что JTA библиотека (где находится класс SystemException) присутствует в class-path. Поэтому придется все же в Surfire плагине использовать модуль java.xml.bind:
Перезапускаем сборку Maven и получаем новое исключение:
В чем заключается ошибка? Hibernate пытается через reflection сделать публичным метод, который является protected или private. До Java 9 это было небезопасно, но возможно. Сейчас это запрещено, если только модуль, в котором находится метод, не объявлен открытым (open). Однако есть лазейка, помогает обойти это ограничение. Нужно добавить к аргументам JVM строку —add-opens java . base/java . lang=ALL-UNNAMED
Здесь мы указываем название модуля, затем пакет и тот модуль, для которого мы открываем доступ. Так как наш проект не использует модули, то мы указываем константу ALL-UNNAMED, которой открыт доступ для всех анонимных модулей. Анонимные модули — это обычные jar файлы, в которых нет файла конфигурации module-info . class. Они были добавлены, чтобы разработчикам библиотек было легче перейти на Java 9.
Добавляем эту строку к аргументам командной строки для плагина Surfire и перезапускаем сборку Maven. Получаем новое исключение, но уже при запуске других тестов:
Как вы видите из stacktrace, проблема происходит на стадии инициализации JMockit. Что можно сделать? Можно обновить версию Jmockit с 1.30 на 1.32. Но это не помогает. Уже готовится версия JMockit, но она все еще в стадии beta. Анализ исходников JDK позволяет обнаружить системную переменную JVM, которая позволяет присоединиться к текущей JVM из нее самое. Нужно лишь установить этот флаг в true: -Djdk.attach.allowAttachSelf=true. Подробнее можно прочесть здесь
Добавляем флаг к параметрам в Surefire плагине и перезапускаем сборку Maven. Получаем новую ошибку:
Подробнее об этой проблеме можно прочесть здесь.
А лечится она обновлением версии war-плагина с 2.6 на 3.1.0:
Меняем версию и перезапускаем сборку. Получаем новую ошибку:
С похожей проблемой мы уже сталкивались. Нужно лишь «открыть» доступ к пакетам, добавив параметры в MAVEN_OPTS:
Перезапускаем сборку Maven и получаем новую ошибку:
Stacktrace говорит об ошибке более подробно:
Проблема в том, что такого класса больше нет в JDK. Можно вручную добавить необходимые классы, как сделали здесь.
А можно обновить версию Lombok (c 1.16.14 до 1.16.16):
Перезапускаем сборку Maven и получаем новое исключение при запуске тестов:
После небольшого исследования выяснилось, что проблема исходит от библиотеки тестирования JGlue, однако его последняя версия была выпущена в июле 2016 года и неизвестно, насколько быстро выйдет новая версия.
На этом мое тестирование Maven завершилось. Часть проблем удалось решить, но в целом, их довольно много как для одного проекта. Проект собирается успешно, но часть тестов при этом не проходит.
Системы сборки. Gradle
Теперь проверим, насколько совместим Gradle с JDK 9. Возьмем последнюю версию первого — 3.5.0, обновим Lombok зависимость и запустим сборку: gradle clean install.
Получим довольно малоинформативную ошибку: java.lang.ExceptionInInitializerError (no error message). Поэтому добавим флаг —stacktrace, который даст больше информации:
Для того, чтобы избавиться от этой ошибки, добавляем знакомый аргумент add-opens в системную переменную GRADLE_OPTS:
Подробнее можно прочитать здесь и здесь.
Перезапускаем сборку Gradle, получаем новую ошибку:
В результат длительного исследования оказывается, что ситуация не так проста, как для Maven. Дело в том, что во время сборки в Gradle запускается несколько JVM процессов, одни процессы могут порождать другие. Можно сделать fork процессов и главное, чтобы все они использовали одни и те же аргументы JVM. С помощью GRADLE_OPTS добиться этого невозможно. Поэтому была придумана новая системная переменная JDK_JAVA_OPTIONS, которая используется всеми JVM процессами в Gradle (подробней о ней здесь). Более того, начиная со сборки b157 появилась системная переменная JDK_JAVAC_OPTIONS для передачи параметров в Java компилятор (javac). Установим JDK_JAVA_OPTIONS в следующее значение:
И перезапустим сборку. У нас выпало исключение:
Такой ошибки у нас еще не было. Суть ее в том, что мы хотим получить доступ к классам из JDK, которые находятся в пакетах, не указанных модулем как экспортируемых (exported) в module-info.java. Это можно обойти, если добавить в JAVA_JDK_OPTIONS «—add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED»
Теперь сборка прошла успешно. Запустим тесты: gradle test. Тесты посыпались с теми же ошибками, что и в Maven. Это можно исправить, просто указав аргументы JVM в блоке test:
Мы все еще используем source/target compatibility 1.8 в нашем проекте. Если мы поменяем их на 1.9, то при компиляции получим ошибку:
Все потому что мы перешли на 1.9, а значит должны оформлять наши проекты в модули, писать module-info.java и в них указать, чтобы нам нужен (requires) тот или иной модуль из JDK. Ситуация становится интересней для Maven/Gradle зависимостей. Здесь можно прочесть о том, как конфигурировать модули, если они содержат одинаковые пакеты.
Однако пока Gradle еще не полностью готов к Java 9, вы можете запускать его под Java 8, а компилировать проект под Java 9. Для этого нужно в скрипте сборки указать конфигурацию под версию:
Тестирование REST-контейнеров
Так как я в своем докладе рассказывал про REST-контейнеры и веб-сервера, то интересно будет их проверить на совместимость с Java 9, тем более что это достаточно сложные технологии.
Начнем с Ratpack. Это довольно новый сервер, полностью написанный на Java 8 и основанный на Netty. Если мы запустим его, то получим исключение:
Нам нужно лишь добавить модуль java.activation при старте сервера, чтобы это починить:
Теперь перейдем к Apache CXF. Для него нужно указать другой модуль:
Для запуска приложения с Jersey (JAX-RS) я использую Jetty сервер. Jersey тоже требует предыдущий модуль.
Я думаю, что вы знаете либо слышали, что летом этого года выходят Spring Framework 5 и Spring Boot 2.0, специально приуроченные к выходу JDK 9 и даже использующие некоторые ее возможности. Пока они не вышли, интересно проверить текущие версии (Spring Boot 1.5.3 и Spring Framework 4.3.8) на «запускаемость».
Spring Boot поддерживает три встроенных сервера: Tomcat, Jetty и Undertow. К сожалению, у меня не получилось запустить REST-приложение ни на одном из них. Оно просто зависало на стадии загрузки.
JMeter — одна из наиболее популярных утилит для тестирования веб-приложений. Она может работать как в консольном варианте, так и в режиме с UI. Готово ли оно к Java 9? Если мы возьмем последнюю версию (3.2) и запустим jmeter.bat, то увидим в консоли ошибку:
Это достаточно странное сообщение, которое судя по всему печатает не JVM. Если мы заглянем в исполняемый файл, то увидим целые блоки кода, где сначала выполняется команда «java-version», потом ее результат парсится и из него выделяется старшая и младшая версии. Причем JMeter предполагает, что результат будет в формате 1.8.0.
Так как в Java 9 результат уже в формате 9.0.0 (openjdk.java.net/jeps/223), то это приводит к катастрофическим последствиям и аварийному завершению приложения. Причем JMeter даже не пишет, что версия неправильная, а просто говорит, что не может найти Java.
Выход заключается в том, чтобы удалить все эти проверки и тогда утилита запустится корректно. Однако при загрузке конфигурации мы получим исключение:
Для того, чтобы избежать подобных ошибок, нужно лишь добавить в JVM аргументы в скрипте строку:
Заключение и спасительный флаг
Как вы видите, в последний год вендорами была проделана большая работа по обеспечению совместимости с Java 9. Это тем более было трудно, что даже в этом году были некоторые изменения в API JDK. Тем не менее многие библиотеки уже успешно работают над Java 9, некоторые без каких-либо ухищрений, некоторые с дополнительными аргументами для JVM.
Тем не менее, выяснять и разбираться в настройках не так приятно, поэтому в конце марта 2017 года руководство Oracle решило упростить жизнь разработчикам и добавить новый спасительный флаг, который упростит миграцию на Java 9, но будет удален в Java 10.
Этот флаг —permit-illegal-access разрешает доступ всем анонимным модулям через reflection к коду именованных модулей и позволяет не писать многочисленные —add-opens. Единственный минус этого флага — он будет выводить предупреждения в консоль обо всех случаях несанкционированного доступа.
Однако оказалось, что, хотя этот флаг и избавляет от необходимости указывать многочисленные —add-opens, он не избавляет от необходимости указывать самого себя. Поэтому начиная со сборки b172 его предполагается заменить на флаг —illegal-access. У этого флага будет четыре значения:
- permit. Это значение по умолчанию, которое открывает доступ через reflection из всех анонимных модулей во все пакеты именованных модулей. При этом значении только один раз печатается предупреждение о попытке доступа.
- warn. Каждая попытка получить доступ через reflection приводит к выводу предупреждения.
- debug. Здесь к выводу предупреждения выводится еще и stacktrace операции.
- deny. Планируется сделать дефолтным в Java 10. Запрещает доступ через reflection для всех пакетов в именованных модулях, кроме указанных явно в —add-opens.
Подробнее можно прочесть здесь. Интересно, что на момент сборки b173 этот флаг все еще не добавлен.
Я надеюсь, что вам было полезно это руководство и миграция ваших приложений будет более простой и быстрой.
Источник
How to Handle the Exception In Initializer Runtime Error in Java
Table of Contents
Introduction to Runtime Errors & Exceptions
Unlike compile-time errors which are detected during compilation [1], runtime errors occur during program execution, i.e. runtime. Java’s runtime error hierarchy is somewhat complicated compared to other programming languages, but at the basic level there are two main categories: runtime errors and runtime exceptions, the latter of which being further divided into checked and unchecked exceptions (see Figure 1 below). Unchecked exceptions are also lumped into the somewhat confusingly named RuntimeException superclass, while all runtime errors are also considered to be unchecked. The term “unchecked” refers to errors and exceptions that Java doesn’t require to be caught or otherwise specified in the code [2]. Runtime Java errors and exceptions are otherwise jointly referred to as throwables, as per the name of the Throwable class—the parent class of all errors and exceptions in this language [3].
Figure 1. Java runtime errors & exceptions hierarchy [4]
ExceptionInInitializerError Error: What, Why & How?
After successfully compiling a program, the Java Virtual Machine (JVM) performs dynamic loading, linking, and initializing of classes and interfaces, broadly known as the class loading process [5]. This process includes the evaluation of all static initializer blocks and variable assignments present in the compiled code. If, during this evaluation, any unexpected exception occurs, the JVM throws an ExceptionInInitializerError runtime error, points to the specific exception that caused the error, and subsequently exits the program.
The ExceptionInInitializerError error occurs every time there is an unchecked (and uncaught) exception taking place inside a static initializer or a static variable assignment. The JVM wraps this exception inside an instance of the java.lang.ExceptionInInitializerError class (which itself is a subclass of the more generic java.lang.LinkageError class of errors [6]) and maintains a reference to it as the root cause.
How to handle the ExceptionInInitializerError Error
To avoid this error, simply ensure that:
- static initializers of classes do not throw any unchecked exception, and that
- static class variable initializations do not throw any unchecked exceptions.
Источник
Improve Article
Save Article
Improve Article
Save Article
An unexpected, unwanted event that disturbed the normal flow of a program is called an Exception.
There are mainly two types of exception in Java:
1. Checked Exception
2. Unchecked Exception
ExceptionInInitializerError is the child class of the Error class and hence it is an unchecked exception. This exception is rise automatically by JVM when JVM attempts to load a new class as, during class loading, all static variables and static initializer block are being evaluated. This exception also acts as a signal that tells us that an unexpected exception has occurred in a static initializer block or in the assignment of value to the static variable.
There are basically two cases when ExceptionInInitializerError can occur in a Java Program:
1. ExceptionInInitializerError While Assigning Value To The Static Variable
In the below example we assign a static variable to 20/0 where 20/0 gives an undefined arithmetic behavior and hence there occurs an exception in the static variable assignment and ultimately we will get ExceptionInInitializerError.
Java
class
GFG {
static
int
x =
20
/
0
;
public
static
void
main(String[] args)
{
System.out.println(
"The value of x is "
+ x);
}
}
2. ExceptionInInitializerError While Assigning Null Value Inside A Static Block
In the below example we have declared a static block inside which we create a string s and assign a null value to it, and then we are printing the length of string, so we will get NullPointerException because we were trying to print the length of a string that has its value as null and as we see that this exception occurs inside the static block, so we will get ExceptionInInitializerError.
Java
class
GFG {
static
{
String s =
null
;
System.out.println(s.length());
}
public
static
void
main(String[] args)
{
System.out.println(
"GeeksForGeeks Is Best"
);
}
}
How to Resolve Java.lang.ExceptionInInitializerError ?
- We can resolve the java.lang.ExceptionInInitializerError by ensuring that static initializer block of classes does not throw any Runtime Exception.
- We can resolve also resolve this exception by ensuring that the initializing static variable of classes also doesn’t throw any Runtime Exception.
buildscript {
repositories {
maven { url = 'https://files.minecraftforge.net/maven' }
jcenter()
mavenCentral()
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:3.+'
}
}
apply plugin: 'net.minecraftforge.gradle'
// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
apply plugin: 'eclipse'
apply plugin: 'maven-publish'
version = '1.0'
group = 'com.yourname.modid' // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = 'modid'
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
minecraft {
// The mappings can be changed at any time, and must be in the following format.
// snapshot_YYYYMMDD Snapshot are built nightly.
// stable_# Stables are built at the discretion of the MCP team.
// Use non-default mappings at your own risk. they may not always work.
// Simply re-run your setup task after changing the mappings to update your workspace.
//mappings channel: 'snapshot', version: '20171003-1.12'
mappings channel: 'snapshot', version: '20171003-1.12'
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
// accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
// Default run configurations.
// These can be tweaked, removed, or duplicated as needed.
runs {
client {
workingDirectory project.file('run')
// Recommended logging data for a userdev environment
property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP'
// Recommended logging level for the console
property 'forge.logging.console.level', 'debug'
}
server {
// Recommended logging data for a userdev environment
property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP'
// Recommended logging level for the console
property 'forge.logging.console.level', 'debug'
}
}
}
dependencies {
// Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed
// that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied.
// The userdev artifact is a special name and will get all sorts of transformations applied to it.
minecraft 'net.minecraftforge:forge:1.12.2-14.23.5.2854'
// You may put jars on which you depend on in ./libs or you may define them like so..
// compile "some.group:artifact:version:classifier"
// compile "some.group:artifact:version"
// Real examples
// compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env
// compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env
// The 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime.
// provided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
// These dependencies get remapped to your current MCP mappings
// deobf 'com.mod-buildcraft:buildcraft:6.0.8:dev'
// For more info...
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
// http://www.gradle.org/docs/current/userguide/dependency_management.html
}
// Example for how to get properties into the manifest for reading by the runtime..
jar {
manifest {
attributes([
"Specification-Title": "examplemod",
"Specification-Vendor": "examplemodsareus",
"Specification-Version": "1", // We are version 1 of ourselves
"Implementation-Title": project.name,
"Implementation-Version": "${version}",
"Implementation-Vendor" :"examplemodsareus",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")*
])
}
}
// Example configuration to allow publishing using the maven-publish task
// This is the preferred method to reobfuscate your jar file
jar.finalizedBy('reobfJar')
// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing
//publish.dependsOn('reobfJar')
publishing {
publications {
mavenJava(MavenPublication) {
artifact jar
}
}
repositories {
maven {
url "file:///${project.projectDir}/mcmodsrepo"
}
}
}
public
class
ExceptionInInitializerError
extends LinkageError
java.lang.Object | ||||
↳ | java.lang.Throwable | |||
↳ | java.lang.Error | |||
↳ | java.lang.LinkageError | |||
↳ | java.lang.ExceptionInInitializerError |
Signals that an unexpected exception has occurred in a static initializer.
An ExceptionInInitializerError
is thrown to indicate that an
exception occurred during evaluation of a static initializer or the
initializer for a static variable.
As of release 1.4, this exception has been retrofitted to conform to
the general purpose exception-chaining mechanism. The «saved throwable
object» that may be provided at construction time and accessed via
the getException()
method is now known as the cause,
and may be accessed via the Throwable#getCause()
method, as well
as the aforementioned «legacy method.»
Summary
Public constructors |
---|
Constructs an |
Constructs a new |
Constructs an ExceptionInInitializerError with the specified detail |
Public methods |
|
---|---|
|
Returns the cause of this error (the exception that occurred |
|
Returns the exception that occurred during a static initialization that |
Inherited methods |
||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
From class java.lang.Throwable
|
||||||||||||||||||||||||||
From class java.lang.Object
|
Public constructors
ExceptionInInitializerError
public ExceptionInInitializerError ()
Constructs an ExceptionInInitializerError
with
null
as its detail message string and with no saved
throwable object.
A detail message is a String that describes this particular exception.
ExceptionInInitializerError
public ExceptionInInitializerError (Throwable thrown)
Constructs a new ExceptionInInitializerError
class by
saving a reference to the Throwable
object thrown for
later retrieval by the getException()
method. The detail
message string is set to null
.
Parameters | |
---|---|
thrown |
Throwable : The exception thrown |
ExceptionInInitializerError
public ExceptionInInitializerError (String s)
Constructs an ExceptionInInitializerError with the specified detail
message string. A detail message is a String that describes this
particular exception. The detail message string is saved for later
retrieval by the Throwable#getMessage()
method. There is no
saved throwable object.
Parameters | |
---|---|
s |
String : the detail message |
Public methods
getCause
public Throwable getCause ()
Returns the cause of this error (the exception that occurred
during a static initialization that caused this error to be created).
Returns | |
---|---|
Throwable |
the cause of this error or null if thecause is nonexistent or unknown. |
getException
public Throwable getException ()
Returns the exception that occurred during a static initialization that
caused this error to be created.
This method predates the general-purpose exception chaining facility.
The Throwable#getCause()
method is now the preferred means of
obtaining this information.
Returns | |
---|---|
Throwable |
the saved throwable object of thisExceptionInInitializerError , or null if this ExceptionInInitializerError has no savedthrowable object. |
Introduction to Runtime Errors & Exceptions
Unlike compile-time errors which are detected during compilation [1], runtime errors occur during program execution, i.e. runtime. Java’s runtime error hierarchy is somewhat complicated compared to other programming languages, but at the basic level there are two main categories: runtime errors and runtime exceptions, the latter of which being further divided into checked and unchecked exceptions (see Figure 1 below). Unchecked exceptions are also lumped into the somewhat confusingly named RuntimeException
superclass, while all runtime errors are also considered to be unchecked. The term “unchecked” refers to errors and exceptions that Java doesn’t require to be caught or otherwise specified in the code [2]. Runtime Java errors and exceptions are otherwise jointly referred to as throwables, as per the name of the Throwable
class—the parent class of all errors and exceptions in this language [3].
ExceptionInInitializerError Error: What, Why & How?
After successfully compiling a program, the Java Virtual Machine (JVM) performs dynamic loading, linking, and initializing of classes and interfaces, broadly known as the class loading process [5]. This process includes the evaluation of all static initializer blocks and variable assignments present in the compiled code. If, during this evaluation, any unexpected exception occurs, the JVM throws an ExceptionInInitializerError
runtime error, points to the specific exception that caused the error, and subsequently exits the program.
The ExceptionInInitializerError
error occurs every time there is an unchecked (and uncaught) exception taking place inside a static initializer or a static variable assignment. The JVM wraps this exception inside an instance of the java.lang.ExceptionInInitializerError
class (which itself is a subclass of the more generic java.lang.LinkageError
class of errors [6]) and maintains a reference to it as the root cause.
How to handle the ExceptionInInitializerError Error
To avoid this error, simply ensure that:
- static initializers of classes do not throw any unchecked exception, and that
- static class variable initializations do not throw any unchecked exceptions.
ExceptionInInitializerError Error Examples
Unchecked exception during static variable initialization
Figure 2(a) shows how an unchecked exception such as an instance of the java.lang.ArithmeticException
triggers the ExceptionInInitializerError
error. The error message denotes the division by zero arithmetic exception as the cause for the error and points to the specific class and line of code where it happened. Eradicating this arithmetic error, as shown in Figure 2(b), solves the issue.
(a)
package rollbar;
public class EIIE {
private static int x = 20 / 0;
public static void main(String... args) {
System.out.println(x);
}
}
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.ArithmeticException: / by zero
at rollbar.EIIE.<clinit>(EIIE.java:4)
(b)
package rollbar;
public class EIIE {
private static int x = 20 / 10;
public static void main(String... args) {
System.out.println(x);
}
}
2
Unchecked exception inside static initializer
Having an unchecked exception thrown inside a static initializer will inevitably trigger the ExceptionInInitializerError
runtime error. Figure 3(a) shows how invoking the String::length
method on a non-initialized String
variable (whose value defaults to null
) throws the NullPointerException
, which in turn triggers the ExceptionInInitializerError
error, because the exception occurred inside the static initializer of the class. To handle this type of scenario, one can implement a simple null guard (Figure 3(b)), or use a try-catch
block to explicitly catch and handle the exception (Figure 3(c)). Note that these approaches assume that there is no logical error in the rest of the code, and that the desired functionality is correctly implemented.
(a)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package rollbar;
public class EIIE2 {
private static String str;
private static long len;
static {
len = str.length();
}
public static void main(String... args) {
System.out.println("String: " + str);
System.out.println("Length: " + len);
}
}
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.NullPointerException: Cannot invoke "String.length()" because "rollbar.EIIE2.str" is null
at rollbar.EIIE2.<clinit>(EIIE2.java:8)
(b)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package rollbar;
public class EIIE2 {
private static String str;
private static long len;
static {
len = str == null ? -1 : str.length();
}
public static void main(String... args) {
System.out.println("String: " + str);
System.out.println("Length: " + len);
}
}
String: null
Length: -1
(c)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package rollbar;
public class EIIE2 {
private static String str;
private static long len;
static {
try {
len = str.length();
} catch (NullPointerException e) {
len = -1;
}
}
public static void main(String... args) {
System.out.println("String: " + str);
System.out.println("Length: " + len);
}
}
String: null
Length: -1
Checked exception inside static initializer?
Since it is impossible to throw checked exceptions from a static block (this is not allowed and will result in a compile-time error), it is good practice to wrap them inside an ExceptionInInitializerError
instance manually, as shown in Figure 4. This is a clean way of handling checked exceptions in static initializers where their use is warranted, and it stays true to the design principles of the language. For completeness, if the checked exception in question doesn’t get thrown, the ExceptionInInitializerError
isn’t thrown either and the code executes normally (Figure 4(b)).
(a)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package rollbar;
import java.lang.reflect.Field;
public class EIIE3 {
private static Field fieldInfo;
static {
try {
fieldInfo = EIIE3.class.getDeclaredField("x");
} catch (NoSuchFieldException e) {
throw new ExceptionInInitializerError(e);
}
}
public static void main(String... args) {
System.out.println(fieldInfo.getName());
System.out.println(fieldInfo.getType());
}
}
Exception in thread "main" java.lang.ExceptionInInitializerError
at rollbar.EIIE3.<clinit>(EIIE3.java:12)
Caused by: java.lang.NoSuchFieldException: x
at java.base/java.lang.Class.getDeclaredField(Class.java:2569)
at rollbar.EIIE3.<clinit>(EIIE3.java:10)
(b)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package rollbar;
import java.lang.reflect.Field;
public class EIIE3 {
private static Field fieldInfo;
static {
try {
fieldInfo = EIIE3.class.getDeclaredField("x");
} catch (NoSuchFieldException e) {
throw new ExceptionInInitializerError(e);
}
}
private static double x;
public static void main(String... args) {
System.out.println(fieldInfo.getName());
System.out.println(fieldInfo.getType());
}
}
x
double
Conclusion
Runtime errors occur during the execution of a program and as such are more difficult to prevent than compile-time errors. In Java, some of these errors are triggered during the class loading process, or in colloquial terms, when the program is starting up. This allows for a certain category of errors to be detected at a very early stage, despite the program having been successfully compiled. One such error is the ExceptionInInitializerError
error which signals that an unexpected exception has occurred during the evaluation of a static initializer or the initialization of a static variable. This error serves as a runtime wrapper for the underlying exception and halts the JVM until the underlying exception is resolved.
Track, Analyze and Manage Errors With Rollbar
![Rollbar in action](https://rollbar.com/wp-content/uploads/2022/04/section-1-real-time-errors@2x-1-300×202.png)
Managing errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Java errors easier than ever. Sign Up Today!
References
[1] Rollbar, 2021. How to Fix «Illegal Start of Expression» in Java. Rollbar Editorial Team. [Online]. Available: https://rollbar.com/blog/how-to-fix-illegal-start-of-expression-in-java/. [Accessed Jan. 7, 2022]
[2] Oracle, 2021. Unchecked Exceptions — The Controversy (The Java™ Tutorials > Essential Java Classes > Exceptions). Oracle and/or its affiliates. [Online]. Available: https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html. [Accessed Jan. 7, 2022]
[3] Oracle, 2021. Throwable (Java SE 17 & JDK 17). Oracle and/or its affiliates. [Online]. Available: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Throwable.html. [Accessed Jan. 7, 2022]
[4] M. Sanger, 2018. Java Exception Hierarchy. Manish Sanger. [Online]. Available: https://www.manishsanger.com/java-exception-hierarchy/. [Accessed Jan. 7, 2022]
[5] Oracle, 2021. Chapter 5. Loading, Linking, and Initializing. Oracle Corporation and/or its affiliates. [Online]. Available: https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-5.html. [Accessed Jan. 7, 2022]
[6] Oracle, 2021. LinkageError (Java SE 17 & JDK 17). Oracle and/or its affiliates. [Online]. Available: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/LinkageError.html. [Accessed Jan. 7, 2022]