Пример программы JNA java.lang.NoClassDefFoundError

Я могу скомпилировать этот пример кода JNA (из шага 2 https://github.com/twall/jna/#getting_started):

package com.sun.jna.examples;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;

/** Simple example of JNA interface mapping and usage. */
public class HelloWorld {

    // This is the standard, stable way of mapping, which supports extensive
    // customization and mapping of Java to native types.
    public interface CLibrary extends Library {
        CLibrary INSTANCE = (CLibrary)
            Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),
                               CLibrary.class);

        void printf(String format, Object... args);
    }

    public static void main(String[] args) {
        CLibrary.INSTANCE.printf("Hello, World\n");
        for (int i=0;i < args.length;i++) {
            CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]);
        }
    }
}

...используя javac -classpath .:jna.jar -g HelloWorld.java без ошибок. (Я скачал jna.jar и пока поместил его в тот же каталог, что и HelloWorld.java.)

Но когда я запускаю его с помощью java -classpath .:jna.jar HelloWorld, я получаю:

Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld (wrong name: com/sun/jna/examples/HelloWorld)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)

Я получаю точно такое же исключение в Mac OS X и Linux.

Как мне заставить это работать?


person Daryl Spitzer    schedule 20.11.2009    source источник


Ответы (3)


В этом примере (как и в подавляющем большинстве классов Java) используются пакеты:

package com.sun.jna.examples;

Чтобы правильно скомпилировать / запустить его, вам нужно запустить javac / java из «корневой» папки (например, из папки, где находится «com»):

Допустим, у вас есть папка с именем examples. Вы бы поместили туда и jna.jar, и исходный код, сохраняя структуру папок:

/examples
 jna.jar
 /com
   /sun
      /jna
         /examples
           HelloWorld.java

Вы компилируете и запускаете, используя:

javac -classpath .:jna.jar -g com/sun/jna/examples/HelloWorld.java

java -classpath .:jna.jar com.sun.jna.examples.HelloWorld

Обратите внимание на разделители путей в первом случае и точки во втором.

person ChssPly76    schedule 20.11.2009
comment
При компиляции вы также хотите включить -d . также флаг, чтобы убедиться, что он разрушает базу структуры каталогов в пакете. В противном случае файл класса будет просто находиться в текущем каталоге. - person Rob Di Marco; 21.11.2009
comment
Роб, не стал бы добавлять -d . при компиляции поместите файл класса в текущий каталог. Похоже, что по умолчанию он помещается в исходный файл .java. Почему я не хочу этого делать? - person Daryl Spitzer; 21.11.2009
comment
@Rob - флаг -d указывает целевую папку, но он не имеет ничего общего с разрушением структуры каталогов на основе пакета. Последнее всегда имеет место. - person ChssPly76; 21.11.2009
comment
@Daryl - возможно, вы не захотите этого делать в реальном проекте; хранить исходный код отдельно от артефактов сборки — хорошая идея по многим причинам (например, упростить проверку исходных кодов в системе контроля версий). Однако для ваших целей (запуск примера) это совершенно нормально. - person ChssPly76; 21.11.2009
comment
Я попытался удалить файлы классов и выполнить компиляцию с помощью javac -classpath .:jna.jar -g -d . com/sun/jna/examples/HelloWorld.java, но HelloWorld.class и HelloWorld$CLibrary.class по-прежнему создаются в com/sun/jna/examples/ (с HelloWorld.java). - person Daryl Spitzer; 21.11.2009
comment
@ Дэрил - как и должно быть. Указание -d . это то же самое, что не указывать его вообще. Если вы хотите попробовать, создайте другую папку с именем build (в /examples) и укажите -d build как параметр javac. Имейте в виду, что впоследствии вам придется добавить его в путь к классам для вызова java: java -classpath build:jna.jar com.sun.jna.examples.HelloWorld - person ChssPly76; 21.11.2009
comment
Остерегайтесь правильного вызова java.exe. Это java [параметры] класс [аргументы]. Поэтому убедитесь, что у вас есть параметр -classpath перед именем вашего класса. - person Andreas; 28.04.2018

Либо просто удалите эту строку и перекомпилируйте (в данном случае это нормально, поскольку вы просто пробуете какой-то пример)

package com.sun.jna.examples;

или прочитайте, что такое пакеты в java и как с ними нужно обращаться (сообщения ChssPly76s в качестве стартера).

Лучше выбрать второй вариант, так как рано или поздно (вероятнее, раньше) вам все равно придется иметь дело с пакетами. Так что просто найдите время, чтобы прочитать об этом.

person jitter    schedule 20.11.2009

В Eclipse в разделе Java Build path > Order and export выберите export jna.jar.

person user2408280    schedule 08.11.2013