1. Главная страница » Компьютеры

Java lang noclassdeffounderror java lang object

Автор: | 16.12.2019

Содержание

Данная статья представляет перевод оригинальных публикаций следующих авторов:

Переводчик выражает благодарность Виктору Жуковскому за ценные правки и обсуждение рукописи.

Введение

Известно насколько неприятно видеть исключение java.lang.NoClassDefFoundError в потоке " main ". Многие разработчики проводят много времени прежде всего пытаясь понять, что пошло не так, какого класса не хватает и в чём суть проблемы. Во-первых, они путают между собой ClassNotfoundException и NoClassDefFoundError , хотя на самом деле это два совершенно разных исключения. Во-вторых, они используют метод «научного тыка» для решения проблемы NoClassDefFoundError вместо ясного понимания почему ошибка случилась и как её исправить. В этой статье по Java мы откроем некоторые секреты исправления ошибки NoClassDefFoundError в Java и поделимся своим опытом решения подобной проблемы.

Ошибка NoClassDefFoundError не является чем-то, что не может быть устранено или чем-то, что очень трудно устраняемо — нет, NoClassDefFoundError всего лишь проявление другой, более глубинной ошибки, что сбивает с толку большинство Java разработчиков. NoClassDefFoundError наиболее распространённая ошибка в Java разработке наряду с java.lang.OutOfMemoroyError: Java heap space и java.lang.OutOfMemoryError: PermGen space . Давайте посмотрим почему в Java происходит NoClassDefFoundError и что делать, чтобы её исправить.

Читайте также:  Nikon 70 300 отзывы

В чём причина NoClassDefFoundError в Java?

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

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

Exception in thread "main" java.lang.NoClassDefFoundError

Фраза Exception in thread "main" означает, что именно поток " main " не может найти определённый класс. Вместо " main " может быть любой поток. Разница между тем, когда эта ошибка возникает в потоке " main " и в другом потоке в состоит том, что при возникновении в потоке " main " программа останавливается, а при возникновении в ином потоке, напротив, продолжает выполнение после ошибки.

Разница между java.lang.NoClassDefFoundError и ClassNotFoundException в Java

Прежде чем рассмотреть разницу между ClassNotFoundException и NoClassDefFoundError давайте рассмотрим, что между ними общего и что приводит к путанице между этими двумя ошибками:

  • Обе ошибки связаны с недоступностью класса во время выполнения;
  • Обе ошибки связаны с Java Classpath .

Теперь о различиях.

  • ClassNotFoundException возникает в Java, если мы пытаемся загрузить класс во время выполнения используя методы Class.forName() , ClassLoader.loadClass() или ClassLoader.findSystemClass() , причём необходимый класс не доступен для Java. Зачастую причина тому — неправильный Classpath . В большинстве своём нам кажется, что мы используем корректный Classpath , но оказывается, что приложение использует совсем другой Classpath — не тот, который мы ожидали. Например, Classpath , заданный в манифесте jar файла, перезаписывает Classpath в переменной окружения CLASSPATH или опции -cp , заданной при запуске jar файла. В отличие от ClassNotFoundException в случае с NoClassDefFoundError проблемный класс присутствовал во время компиляции, и, поэтому, программа успешно прошла компиляцию, но по некоторой причине класс отсутствует во время исполнения. На мой взгляд решить NoClassDefFoundError легче чем ClassNotFoundException , поскольку вы точно знаете, что класс присутствовал во время сборки, но, в общем случае, это сильно зависит от среды разработки. Если вы работаете с J2EE окружением, вы можете получить NoClassDefFoundError даже если класс присутствует, поскольку он может быть невидимым для соответствующего загрузчика классов.
  • ClassNotFoundException представляет собой проверяемое исключение, унаследованное непосредственно от класса java.lang.Exception , требующее явной обработки, в то время как NoClassDefFoundError это java.lang.Error , унаследованный от java.lang.LinkageError .
  • ClassNotFoundException возникает в результате явной загрузки класса методами Class.forName() , ClassLoader.loadClass() или ClassLoader.findSystemClass() , в то время как NoClassDefFoundError — результат неявной загрузки класса, происходящей при попытке вызова метода из другого класса или доступа к его свойству.

NoClassDefFoundError в Java. Примеры и сценарии

Итак, очевидная причина NoClassDefFoundError состоит в том, что определённый класс не доступен в Classpath , так что нам нужно добавить его в Classpath или понять почему его нет в Classpath , хотя мы ожидаем его там найти. Для этого могут быть несколько причин:

  1. Класс не задан непосредственно в самой переменной Classpath .
    • Распечатайте значение System.getproperty("java.classpath") в Java программе.
    • Проверьте, не перезаписывает ли значение переменной окружения Classpath скрипт, запускающий приложение. Запустите программу с явной опцией -classpath , где укажите тот classpath , который по вашему мнению сработает, и если в этом случае программа заработает, то это хороший знак, что кто-то перезатирает ваш classpath .
    • Класс отсутствует по местоположению, указанному в переменной Classpath .
      • Проверьте, не удалил ли кто-то ваш jar-файл, или быть может переименовал его.
      • Загрузчик классов не имеет прав на чтение файла, указанного в переменной Classpath , на уровне операционной системы.
        • Используйте один и тот же >ClassPath файла манифеста, при запуске программы с помощью команды jar .
          • Если вы используете файл сборки ANT для создания JAR архива и файла манифеста, то проверьте получает ли скрипт сборки ANT правильное значение classpath и добавляет ли его в файл manifest.mf .
          • Виртуальная машина Java не нашла одну из зависимостей, например, нативную библиотеку. Эта ошибка выбрасывается поскольку NoClassDefFoundError является наследником java.lang.LinkageError .
            • Храните ваши dll совместно с jar-файлами.
            • Виртуальная машина Java не смогла завершить статическую инициализацию класса.
              • Проверьте наличие ошибки java.lang.ExceptionInInitializerError в вашем журнале ошибок.
              • Родительский загрузчик классов не видит класс, поскольку тот был уже загружен дочерним загрузчиком. Если вы работаете со средой J2EE, то неверная настройка видимости класса среди загрузчиков классов может также привести к java.lang.NoClassDefFoundError .
              • Опечатка в XML конфигурации также может привести к NoClassDefFoundError в Java. Большинство программных платформ вроде Spring и Struts используют XML конфигурации для определения бинов. Случайно перепутав имя бина, вы можете получить java.lang.NoClassDefFoundError при загрузке другого класса, который зависит от бина. Это случается довольно часто в программных платформах Spring MVC и Apache Struts, где вы получаете тонны ошибок Exception in thread "main" java.lang.NoClassDefFoundError во время установки WAR или EAR файла.
              • Переменные окружения или JDK установлены неверно.
                • Проверьте переменные PATH и JAVA_HOME .
                • Поставьте JDK другой версии.

                Загрузчик классов в Java

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

                • Делегирование означает, что каждый запрос на загрузку класса делегируется родительскому загрузчику классов.
                • Видимость означает возможность найти классы загруженные загрузчиком классов: все дочерние загрузчики классов могут видеть классы, загруженные родительским загрузчиком, но родительский загрузчик не может видеть класс, загруженный дочерним.
                • Уникальность гарантирует, что класс, загруженный родительским загрузчиком, не загружается повторно дочерним загрузчиком.

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

                Так в чём же тут проблема? Если класс A найден и загружен каким-нибудь родительским загрузчиком, это значит, что дочерний загрузчик загружать его уже не будет, а вы, возможно, именно этого и ждёте, что и приводит к NoClassDefFoundError .

                Для лучшего понимания изобразим весь процесс загрузки в контексте платформы Java EE.

                Как вы можете видеть при попытке загрузки класса дочерний загрузчик (Web App #1) делегирует загрузку родительскому загрузчику (Java EE App #1), который в свою очередь делегирует её системному стартовому загрузчику JVM. Если системный стартовый загрузчик не может загрузить класс, он возвращает управление родительскому загрузчику и так далее по цепочке пока класс не будет загружен каким-либо загрузчиком.

                Рассмотрим простой пример, приводящий к NoClassDefFoundError из-за разной видимости классов между дочерним и родительским загрузчиками. Сделаем свой загрузчик MyClassLoader , наследник от java.lang.ClassLoader такой, чтобы он загружал классы с расширением .test вместо .class , находящиеся в пакете net.javacogito . Отметим, что стандартный загрузчик по умолчанию загружает данные только из файлов с расширением .class , так что загрузить Bar.test он не сможет. Схема дальнейшей работы такая:

                1. JVM загружает класс Bar из файла Bar.test .
                2. Класс Bar печатает свой загрузчик классов. Это MyClassLoader .
                3. JVM загружает класс Foo из файла Foo.class .
                4. Класс Foo печатает свой загрузчик классов. Это sun.misc.Launcher.AppClassLoader .
                5. Класс Foo вызывает статический метод printClassLoader() у класса Bar .

                В этот момент JVM выдаёт NoClassDefFoundError , не смотря на то, что Bar был загружен ранее, поскольку родительский загрузчик AppClassLoader не видит классы, загруженные дочерним загрузчиком MyClassLoader .

                Ниже на рисунке изображена схема делегирования загрузки, приводящая к NoClassDefFoundError .

                При запуске любого java-приложения или просто "java" сбой jvm:

                Ошибка при инициализации виртуальной машины
                java/lang/NoClassDefFoundError: java/lang/Object

                Вот список неправильных ответов:

                Верный домашний каталог Java, включая каталог /bin, находится в глобальной PATH

                JAVA_HOME устанавливается правильно

                Выполнение команды java -fullversion работает

                Символьные ссылки в /usr/java указывают на правильную установку java

                Я не устанавливал Java по умолчанию, когда создал систему

                java -version не работает. такая же ошибка, как указано выше

                Выдача команд из-под структуры каталогов java-установки не работает.

                Это 64-разрядная Java для 64-разрядного

                Проблема возникает из-за неправильной установки Java (например, установка без прав администратора или просто распаковка tools.zip).

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

                Проверьте папку JDK для файлов *.pack в jre/lib и jre/lib/ext например rt.pack (по умолчанию используется c:
                ameof_jdk_folderjrelib для Microsoft Windows и /usr/java/lib для Unix/GNU Linux)

                Те файлы *.pack должны быть распакованы в файлы .jar с помощью этой команды:

                %JAVA_HOME%inunpack200 -r -v -l "" rt.pack rt.jar

                Для * nix аналогичная командная строка распаковывает файлы:

                /usr/bin/unpack200 rt.pack rt.jar

                и повторите этот шаг со всеми файлами *.pack и перезапустите свою программу.

                Для java 8 @* ОС NIX:

                Из каталога " /jre/lib" (для меня это:/usr/java/jdk1.8.0_05/jre/lib)

                (Возможно, вы не можете использовать систему unpack200, вызывая проблемы с версией.) Этот файл unpack200 находится в каталоге java 8 (для меня:/usr/java/jdk1.8.0_05/bin)

                Кажется, что для 64-битной архитектуры вам необходимо установить 32-разрядную версию и 64-разрядную версию jre (независимые от архитектуры файлы, такие как rt.jar, распространяются только в 32-разрядной версии).

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

                Быстрое решение для нетерпеливых людей;) На машинах Windows попробуйте следующее: Перейдите в каталог C:WindowsSystem32 и удалите java.exe (или переименуйте его на что-то вроде java.exe.old ).

                Поскольку не менее 1,6, в каталоге Windows не должно быть java.exe . Если есть, то это от чего-то осталось.

                Немного больше:

                Я действительно удивлен, что вопрос с 2012 года еще не получил одобренного ответа, и я действительно столкнулся с той же проблемой в 2015 году на своей 32-разрядной ОС Win 7!

                Так что же произошло?

                В принципе, все работает нормально, я загрузил базу данных H2, и когда я попытался запустить H2 Console (Command Line) , я получил:

                Я нашел этот вопрос, и я смог подтвердить те же симптомы:

                JAVA_HOME устанавливается правильно:

                java -version не работает, а java —fullversion работает нормально:

                РЕШЕНИЕ: Перейдите в каталог C:WindowsSystem32 и удалите (я действительно переименовал) java.exe файл.

                Теперь я получаю:

                и H2 Console (Command Line) отлично работают!

                I was Java running 1.4.2_02 on Mandrake 9.0 without problems and then suddenly following error appeared:and since that. I can’t run Java and get the same error everytime I try to run it.

                I tried seting new environment variable CLASSPATH to and /src.zip and adding to PATH (which at the moment contains only /bin/), but it didn’t help (still the same error.)

                I searched forums to see if there was any solution, and even though isssue of similar error appeared couple times, I didn’t find any usable explanation+solution.

                P.S. general notice: It would be very helpful, if Java messages were less cryptic and more informative (maybe providing some suggestion how to fix the problem). I think it would solve a lot of issues (on this forum as well) that were caused only by undesipherable message given by Java.

                • 15609 Просмотров
                • Метки: нет (добавить)
                1. Re: java/lang/No >

                hmm, reset helped. But that of course isn’t solution to the problem.

                It only fixes current consequences, not cause of it.

                • Мне нравится Показать отметки "Мне нравится" (0) (0)
                • Действия
                2. Re: java/lang/No >

                The error is obvious it couldn’t find a core class.

                Error conditions like this are not worth the JVM developers spending time on. There could be tens if not hundreds of reasons. And it occurs so seldom that it isn’t worth them wasting their time.

                Given that some of the possible reasons could require that you re-install java or even parts of the OS or even hardware, you should be glad that a simple reset fixed it.

                • Мне нравится Показать отметки "Мне нравится" (0) (0)
                • Действия
                3. Re: java/lang/No >

                so tell me how to eliminate its cause if it is so obvious.

                (as far as I can see, you are talking about consequence, not cause of it)

                • Мне нравится Показать отметки "Мне нравится" (0) (0)
                • Действия
                4. Re: java/lang/No >

                As I said there can be tens if not hundreds of causes.

                For example:
                — There could be up to hundred files, drivers, etc that could get corrupted and cause this in the OS
                — Permissions problems
                — Deleted files, deleted directories, even lack of swap space.
                — Corrupted java binaries.
                — Corrupted java class files.
                — Some application locking one of the many java binaries or class files.
                — etc.

                • Мне нравится Показать отметки "Мне нравится" (0) (0)
                • Действия
                5. Re: java/lang/No >

                i too was running fine, then everything stopped working. one second everything was working and the next it stopped working. i found out 4 jar files in the lib directory are missing including rt.jar!

                what could cause these jar file to be missing?

                • Мне нравится Показать отметки "Мне нравится" (0) (0)
                • Действия
                6. Re: java/lang/No >
                • Мне нравится Показать отметки "Мне нравится" (0) (0)
                • Действия
                7. Re: java/lang/No >
                • Мне нравится Показать отметки "Мне нравится" (0) (0)
                • Действия
                8. Re: java/lang/No >

                dalamar66 wrote:
                I have the same problem in SunOs with JDK 1.6.06

                If you were in fact running that VM then you would not get that problem.

                There are only two reasons possible.
                1. Your VM/OS is corrupted.
                2. You are not running the VM that you think you are.

                • Мне нравится Показать отметки "Мне нравится" (0) (0)
                • Действия
                9. Re: java/lang/No >

                dalamar66 wrote:
                I have the same problem in SunOs with JDK 1.6.06

                If you were in fact running that VM then you would not get that problem.

                That’s a bit of an assumption.

                $ which java
                /usr/java/jdk1.6.0_12/bin/java
                malachi@AndroidDev:

                $ java -version
                Error occurred during initialization of VM
                java/lang/NoClassDefFoundError: java/lang/Object

                • Мне нравится Показать отметки "Мне нравится" (0) (0)
                • Действия
                10. Re: java/lang/No >
                • Мне нравится Показать отметки "Мне нравится" (0) (0)
                • Действия
                11. Re: java/lang/No >

                VivLiu wrote:
                I think it caused by the ‘ rt.jar ‘ is missing. Could you found the ‘ rt.jar ‘ in ‘ $JAVA_HOME/jre/lib/ ‘ ?

                The files were there, but it just didn’t work. I installed it by downloading the Linux version from Sun and installing via alien on the Ubuntu VirtualBox.
                Reinstalling using apt-get instead worked fine.

                • Мне нравится Показать отметки "Мне нравится" (0) (0)
                • Действия
                12. Re: java/lang/No >

                dalamar66 wrote:
                I have the same problem in SunOs with JDK 1.6.06

                If you were in fact running that VM then you would not get that problem.

                That’s a bit of an assumption.

                $ which java
                /usr/java/jdk1.6.0_12/bin/java
                malachi@AndroidDev:

                $ java -version
                Error occurred during initialization of VM
                java/lang/NoClassDefFoundError: java/lang/Object

                The fact that you post some text doesn’t alter the fact that a correctly installed and used Sun VM cannot have that problem.

                So one or more of the following is true
                1. It is not a Sun VM.
                2. It is not installed correctly. It is corrupt and/or has been modified.
                3. It is being used incorrectly.

                • Мне нравится Показать отметки "Мне нравится" (0) (0)
                • Действия
                13. Re: java/lang/No >

                malach >VivLiu wrote:
                I think it caused by the ‘ rt.jar ‘ is missing. Could you found the ‘ rt.jar ‘ in ‘ $JAVA_HOME/jre/lib/ ‘ ?

                The files were there, but it just didn’t work. I installed it by downloading the Linux version from Sun and installing via alien on the Ubuntu VirtualBox.
                Reinstalling using apt-get instead worked fine.

                • Мне нравится Показать отметки "Мне нравится" (0) (0)
                • Действия
                14. Re: java/lang/No >

                VivLiu wrote:
                I think it caused by the ‘ rt.jar ‘ is missing. Could you found the ‘ rt.jar ‘ in ‘ $JAVA_HOME/jre/lib/ ‘ ?

                Could be caused by any number of things.

                For instance it might be possible to cause it by opening up the computer and hitting the hard drive with a hammer as you start up the application.

                However that, as with your suggestion, is pointless, since it is not a VM problem but rather a user/environment problem. And those problems need to be fixed at that level.

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

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