NoClassDefFoundError в интерфейсе, а не в классе - PullRequest
4 голосов
/ 12 июля 2011

У меня проблема с NoClassDefFoundError. Я использую интерфейсы, и определение класса не должно быть доступно:

package code;
public interface Constants {...}

Класс, реализующий этот интерфейс, компилируется без каких-либо ошибок, и JAR-файл был создан, но во время выполнения он выдает ошибку.

import ...;
import code.*;
public class MultiDoc extends LanguageAnalyser implements Constants{}

Constants содержит только список констант.

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

Ошибка времени выполнения:

java.lang.NoClassDefFoundError: code/Constants

Какое решение?

Ответы [ 6 ]

9 голосов
/ 12 июля 2011

Проверьте статическую инициализацию этого класса. Посмотрите здесь: В чем разница между NoClassDefFoundError и ClassNotFoundException .
java.lang.NoClassDefFoundError: code/Constants не означает, что класс Constants отсутствует в CLASSPATH. На самом деле все как раз наоборот. Это означает, что класс был найден ClassLoader, однако при попытке загрузить класс натолкнулся на ошибку при чтении определения класса. Обычно это происходит, когда у рассматриваемого класса есть статические блоки или члены, которые используют класс, который не найден ClassLoader.

2 голосов
/ 12 июля 2011

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

Первое исключение возникает в простом случае, когда JVM ищет «packageB.ClassA» и не может найти его в пути поиска.Я подозреваю, что есть несколько других случаев, но довольно редких.

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

  1. Класс находится, например, в "packageA / ClassA.class", но внутренне называется "packageB / ClassA" (или имя пакета было случайно опущено висточник или файл класса находится в неправильном каталоге, учитывая его имя пакета).
  2. При загрузке класса произошла какая-то ошибка, обычно ошибка при инициализации статического хранилища.
1 голос
/ 12 июля 2011

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

1 голос
/ 12 июля 2011

Если у вас somedirectory/code в вашем пути к классам, то это неправильно .Вам всегда нужен каталог base в вашем пути к классам (в этом случае это будет somedirectory).Сама Java будет искать в этих корнях каталог с именем code, содержащий файл с именем Constants.class.

1 голос
/ 12 июля 2011

Из вашего вопроса я вижу, что скомпилированный интерфейс Constants находится в jar, который отличается от jar / location реализующих классов.Таким образом, вы должны иметь возможность выполнить ваше приложение следующим образом:

java -cp /path-to-jar/JarContainingConstants.jar my.application.Main

(замените имена реальными именами)

Если вы добавили другие классыв другой jar и , затем, если вы сделали этот jar исполняемым, и , то, если , вы попытались запустить его с java -jar MyApplication.jar, , тогда любой путь к классу, определенный вне выполняемогобанка игнорируетсяНо приведенная выше команда может работать с любым jar (исполняемым или нет).


из комментария

[alef@localhost ~]$ java -cp /../code-misc.jar /.../MultiDoc.jar 
Exception in thread "main" java.lang.NoClassDefFoundError: /.../MultiDoc/MultiDoc/jar 
Caused by: java.lang.ClassNotFoundException: .home. 
  ... .MultiDocDateMathcer.jar 
  at java.net.URLClassLoader$1.run(URLClassLoader.java:217) 
  ... 
  at java.lang.ClassLoader.loadClass(ClassLoader.java:266) 
Could not find the main class: /.../MultiDoc/MultiDocr.jar. 
Program will exit.

Вы называете, безусловно, неправильно.Сделайте это так (ОБНОВЛЕНИЕ):

java -Dgate.home=/my/new/gate/home/directory -cp gate.jar;code-misc.jar;MultiDoc.jar gate.Main
0 голосов
/ 02 апреля 2017

Любой интерфейс должен быть объявлен внутри класса.

public class Calbacks {
    public interface IBaseFragmentInterface {
        void NotifyMainActivity();
    }
}

* Я очень долго нахожу решение этой проблемы, но нахожу решение самостоятельно методом научного тыка

...