Отладка кода JNI с помощью Xcode 4 / OS X 10.6
Я рвал на себе волосы, пытаясь выяснить что-то, что является бессмысленным в 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 ответ
Ну вот.
Строим библиотеку
Вы, наверное, знаете, что jni libs на mac должен быть назван в форме libFoo.jnilib. Затем вы загружаете библиотеку из Java, вызывая System.loadLibrary ("Foo");
1. Создайте новый динамический библиотечный проект. Назовите это libSomething. Это половина битвы имен.
2. Найдите целевые параметры сборки для исполняемого расширения. По умолчанию это установлено в dylib. Измените это, чтобы быть jnilib. Это вторая половина битвы имен.
3. Добавьте фреймворк JavaVM в связанные фреймворки. Это содержит JNI.
4. Создайте свой собственный заголовочный файл как обычно.
5. Включите его в свой проект и создайте соответствующий файл.m.
6. Вы должны изменить путь включения для jni.h. На маке это <JavaVM/jni.h>
или используйте инфраструктуру JavaNativeFoundation. Я рекомендую последнее.
7. (необязательно) JavaNativeFoundation предоставляет ряд макросов и методов, которые значительно упростят преобразование данных / методов в / из Java/Objective-C. Это не очень хорошо задокументировано, но это стоит исследовать. Если вы решили использовать JNF, используйте открытый треугольник в инфраструктуре JavaVM. Вы увидите, что JNF является подрамником. Перетащите его на верхний уровень, равный JavaVM. Тогда вы можете начать использовать его. Импортировать <JavaNativeFoundation/JavaNativeFoundation.h>
Выполните поиск в Google на JNF_COCOA_ENTER, чтобы увидеть примеры использования JNF.
Теперь вы должны иметь возможность построить действительную библиотеку jni. Предполагая, что в вашем коде нет ошибок, все готово.;-)
отладка
Я перепробовал все, что нашел на разных веб-страницах, чтобы заставить работать 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 нажмите Mx (опция x). Введите GDB и нажмите Enter. Вы увидите что-то вроде "gdb --annotate=2 xxxxxxxxxx". Нажимайте клавишу Backspace, пока не доберетесь до настройки аннотирования. Введите "pid xxx", где xxx - это pid вашего приложения для вызова Java. В итоге вы должны получить строку, похожую на "gdb --annotate=2 pid xxxx". Нажмите Ввод.
6. Вы должны увидеть, как gdb загружает символы для вашей jni lib.
7. Теперь нажмите Mx. Наберите gdb-many-windows. Нажмите Ввод.
8. Теперь вы должны увидеть несколько окон в Emacs. Окно команды GDB, локальные переменные, исходный код и другие.
9. Введите break someFunctionName в командном окне. Нажмите Ввод.
10. Введите продолжение в командном окне. (Это приводит к продолжению выполнения). Нажмите Ввод.
11. Теперь продолжайте в отладчике Java или нажмите Enter в диалоговом окне Java.
12. Вы должны увидеть, как gdb достиг точки останова в вашем коде jni.
13. Изучите Emacs и GDB. В частности, проверьте команду po в gdb.
14. А Боб твой дядя.
Наслаждайтесь!