Играть в фреймворк java.lang.NoClassDefFoundError только в режиме разработки
Я работаю с protobufs с Play Framework 2.1.3 без проблем. Затем мне нужно было преобразовать protobufs в JSON, поэтому я включил
"com.googlecode.protobuf-java-format" % "protobuf-java-format" % "1.2"
в Build.scala.
Попытка преобразовать любой протобуф в JSON, используя
JsonFormat.printToString(message);
Это приводит к следующей ошибке при работе в режиме разработки (запущен с play run)
play.api.Application$$anon$1: Execution exception[[RuntimeException: java.lang.NoClassDefFoundError: com/google/protobuf/InvalidProtocolBufferException]]
...
Caused by: java.lang.NoClassDefFoundError: com/google/protobuf/InvalidProtocolBufferException
...
Caused by: java.lang.ClassNotFoundException: com.google.protobuf.InvalidProtocolBufferException
at java.net.URLClassLoader$1.run(URLClassLoader.java:202) ~[na:1.6.0_51]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.6.0_51]
at java.net.URLClassLoader.findClass(URLClassLoader.java:190) ~[na:1.6.0_51]
at java.lang.ClassLoader.loadClass(ClassLoader.java:306) ~[na:1.6.0_51]
at java.lang.ClassLoader.loadClass(ClassLoader.java:247) ~[na:1.6.0_51]
at sbt.PlayCommands$$anonfun$53$$anonfun$55$$anon$2.loadClass(PlayCommands.scala:535) ~[na:na]
Если игра запущена в производственном режиме, у меня нет ошибок.
Я смог заставить его работать в режиме разработки, если я поместил исходный код для protobuf-java-format в папку моего приложения. В качестве временного решения это работает, но я хотел бы знать, как правильно решить эту проблему.
Дополнительная информация: В соответствии с предложенным ниже предложением я проверил путь к классу воспроизведения, зависимости воспроизведения и произвел поиск в моей системе, и у меня есть только одна копия файла jar.
Я могу бегать без проблем:
Exception e = new InvalidProtocolBufferException()
NoClassDefFoundError выбрасывается, когда я пытаюсь использовать любой статический метод из библиотеки protobuf-java-format. Например:
XmlFormat.printToString(message)
Не работает в режиме разработки, но работает в производстве (начало игры). Интересно, что класс, который не может найти, отличается:
[RuntimeException: java.lang.NoClassDefFoundError: com/google/protobuf/Message]
Я использую методы из библиотеки protobuf без проблем в других местах, поэтому я знаю, что они включены в путь к классам.
В Google мне удалось найти еще один экземпляр, у которого есть похожие проблемы: https://groups.google.com/forum/
Я не смог понять, как изменить код, чтобы он работал.
1 ответ
Вы уверены, что класс существует в 1.2? Я вижу, что существует в версии 2.3.
Это звучит как проблема загрузчика классов, когда jar-файл protobuf-java находится в одном загрузчике классов, который не имеет доступа к другому jar-файлу. Лучше всего сделать так, чтобы этот jar и другие jar protobuf оказались в одном каталоге, когда вы запускаете приложение, чтобы они оказались в одном загрузчике классов.
Другие вещи, которые вы можете сделать, это вызвать класс в каждом и заставить загрузчика классов и дурачиться, заставляя родителей загрузчиков классов также видеть, как выглядит иерархия загрузчика классов.
Еще один очень полезный метод для отладки при отладке - это XXXXX.class.getProtectionDomain(). GetCodeSource(). GetLocation().
замените XXXXX классом, существующим в protobuf, таким как этот класс Exception, в котором у вашего класса нет проблем с загрузкой, а у protobuf-java-format есть проблемы с загрузкой, а также с любым классом из protobuf-java-формата. Это скажет вам, откуда JVM загружает две банки.