Отладка кода JNI с помощью Xcode 4 / OS X 10.6 - PullRequest
3 голосов
/ 03 июля 2011

Я рвал на себе волосы, пытаясь понять что-то, что является умственно отсталым в Windows / Visual Studio.У меня есть библиотека JNI под OS X 10.6, которую я хотел бы вызвать с помощью исполняемого файла Java и отладки под Xcode: пошаговое выполнение кода, проверка переменных в моей библиотеке JNI, установка точек останова и т. Д.

Вот рабочаяПример JNI, который компилируется и работает нормально из командной строки.Если бы кто-то мог сказать мне, как настроить это в XCode, я был бы бесконечно благодарен.В идеале я хотел бы, чтобы пошаговые инструкции начинались с нуля в Xcode и вырезались и вставлялись из кода ниже, в зависимости от ситуации, что приводило бы к чему-то, что можно отлаживать в Xcode 4 и позволяло мне устанавливать точки останова в коде JNI, исследовать переменныесм. трассировки стеков и т. д.

В знак благодарности я отправлю 20 долларов первому человеку, который даст мне такие инструкции, которые я могу воспроизвести на моем конце, если вы дадите мне адрес Paypal.

Заранее спасибо!

HelloWorld.java

class HelloWorld {
    public native String displayHelloWorld();

    static {
        System.loadLibrary("HelloWorldImp");
    }

    public static void main(String[] args) {
        System.out.println("--> "+new HelloWorld().displayHelloWorld());
    }
}

HelloWorldImp.mm

#include <stdio.h>
#include <jni.h>

#include <string>

#import <Foundation/Foundation.h>

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jstring JNICALL
Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    NSString* name = @"Yo Cocoa";
    std::string s = [name UTF8String];    

    jstring ret = env->NewStringUTF(s.c_str());

    [pool drain];

    return ret;
}

#ifdef __cplusplus
}
#endif

buildjni.sh

gcc -bundle -I/System/Library/Frameworks/JavaVM.framework/Headers -lstdc++ -o libHelloWorldImp.jnilib -framework Foundation HelloWorldImp.mm

1 Ответ

3 голосов
/ 18 ноября 2011

Вот, пожалуйста.

Сборка библиотеки
Вы, наверное, знаете, что jni libs на mac должен быть назван в форме libFoo.jnilib. Затем вы загружаете библиотеку из Java, вызывая System.loadLibrary ("Foo");
1. Создайте новый динамический библиотечный проект. Назовите это libSomething. Это половина битвы имен.
2. Найдите целевые параметры сборки для исполняемого расширения. По умолчанию это установлено в dylib. Измените это, чтобы быть jnilib. Это вторая половина битвы имен.
3. Добавьте фреймворк JavaVM в связанные фреймворки. В этом есть материал JNI.
4. Создайте свой собственный заголовочный файл как обычно.
5. Включите его в свой проект и создайте соответствующий файл .m.
6. Вы должны изменить путь включения для jni.h. На Mac это <JavaVM/jni.h> или , использующий инфраструктуру JavaNativeFoundation. Я рекомендую последнее.
7. (необязательно) JavaNativeFoundation предоставляет ряд макросов и методов, которые значительно упростят преобразование данных / методов в / из Java / Objective-C. Это не очень хорошо задокументировано, но стоит исследовать. Если вы решили использовать JNF, используйте открытый треугольник в инфраструктуре JavaVM. Вы увидите, что JNF является подрамником. Перетащите его на верхний уровень, равный JavaVM. Тогда вы можете начать использовать его. import <JavaNativeFoundation/JavaNativeFoundation.h> Выполните поиск в Google на JNF_COCOA_ENTER, чтобы увидеть примеры использования JNF

Теперь вы должны иметь возможность построить действительную библиотеку jni. Предполагая, что в вашем коде нет ошибок, все готово. ; -)

Debugging
Я перепробовал все, что нашел на разных веб-страницах, чтобы заставить работать JNI в Xcode. Это сработало, но зависало при переходе через вызовы какао. Однако отладка с помощью gdb работает . Это действительно не так уж и плохо, если вы запускаете GDB в Emacs. Недостатком, конечно же, является то, что вам нужно набрать скорость на emacs и gdb, если вы этого еще не сделали. Вот суть:
1. Скомпилируйте вашу библиотеку с отладочными символами
2. Установите точку останова в вашем коде вызова Java после загрузки библиотеки, но перед вызовом кода, который вы хотите отладить. В качестве альтернативы, вы можете поместить туда showMessageDialog. Все, что заблокирует Java-программу в нужной точке.
3. Откройте Activity Monitor и запишите pid вашей java-программы.
4. Запустите Emacs. Если вы находитесь на Lion, терминал emacs, который идет с вами, должен работать. На SL терминальный Emacs не обладает магией GDB. В обоих случаях, однако, я рекомендую вам скачать и использовать Mac Gui Emacs. Доступно более одного, я использую тот, который у меня есть здесь . Если вы используете emacs в терминале, вам нужно перейти в Termina / Preferences / Settings / Keyboard и посмотреть вниз. Есть флажок «использовать опцию как мета-ключ». Вы хотите, чтобы это проверили.
5. При запущенном emacs нажмите M-x (опция x). Введите GDB и нажмите Enter. Вы увидите что-то вроде "gdb --annotate = 2 xxxxxxxxxx". Нажимайте клавишу Backspace, пока не доберетесь до настройки аннотирования Введите «pid xxx», где xxx - это pid вашего приложения для вызова Java. В итоге вы должны получить строку, похожую на «gdb --annotate = 2 pid xxxx». Нажмите ввод.
6. Вы должны увидеть, как gdb загружает символы для вашей библиотеки jni.
7. Теперь нажмите M-x. Наберите gdb-many-windows. Нажмите ввод.
8. Теперь вы должны увидеть несколько окон в Emacs. Окно команды GDB, локальные переменные, исходный код и др.
9. Введите break someFunctionName в командном окне. Нажмите Enter.
10. Введите продолжение в командном окне. (Это приводит к продолжению выполнения). Нажмите ввод.
11. Теперь продолжайте в отладчике Java или нажмите Enter в диалоговом окне Java.
12. Вы должны увидеть, как gdb достиг точки останова в вашем коде jni.
13. Изучите Emacs и GDB. В частности, проверьте команду po в gdb.
14. А Боб твой дядя.

Наслаждайтесь!

...