Хобрук: Ваш путь к мастерству в программировании

Отладка кода Objective C JNI

Вот ситуация:

У меня есть клиентский java-проект, открытый в eclipse. Он использует библиотеку JNI, созданную проектом Xcode Objective C. Есть ли хороший способ отлаживать код C из eclipse при выполнении кода Java? Очевидно, что отладчик eclipse по умолчанию не может войти в файл библиотеки jni, и мы теряем поток (поток означает здесь исследовательский поток, а не поток программирования).

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

Спасибо.

РЕДАКТИРОВАТЬ:

Следует отметить, что причина, по которой библиотека jni написана на Objective-C, заключается в том, что она интегрируется с Mac OSX. Он использует платформу Cocoa для интеграции с голосовым API Apple.


  • этот вопрос может дать некоторое представление, речь идет об использовании gdb в Linux, но, вероятно, он будет работать и для obj-c: stackoverflow.com/questions/9256176/ 08.10.2012
  • если повезет, вы даже можете подключить xcode для удаленной отладки: stackoverflow.com/questions/180987/ 08.10.2012

Ответы:


1

Я не уверен, что полностью понял вашу настройку, и если вам нужно, чтобы это было сделано из eclipse или нет. Во всяком случае, мне было интересно сделать небольшую тестовую программу с использованием JNI и библиотеки Cocoa, которая ничего не делала, просто чтобы попробовать отладить код obj-c/c.

Мне удалось выполнить эту настройку, а также отладить код. Я использую IntelliJ для Java и Xcode для части objc/c, но выполнение части java в eclipse не составляет труда.

Таким образом, вы сможете точно настроить структуру моего проекта и приступить к отладке. И оттуда вы сможете применить эти знания к своему собственному более сложному коду.

Вот как я начал:

  • Создайте новый проект в Xcode, выбрав Cocoa Library.

Библиотека какао

  • Назовите проект libnative и сделайте его динамическим.

Выберите параметры

  • Выберите место для вашего нового проекта. Я использую ~/Development/ и пропускаю часть Create local git....

  • Это создаст новый проект с именем lib native.xcodeproj в выбранной вами папке. Были автоматически созданы два файла: libnative.h и libnative.m.

  • Сначала вы должны изменить настройки проекта.

    • Executable Extension in the Packaging section must be changed from dynlib to jnilib.
    • Framework Search Paths в разделе Search Paths необходимо обновить, чтобы указать на структуру JNI: /System/Library/Frameworks/JavaVM.framework/Frameworks/JavaNativeFoundation.framework/

введите здесь описание изображения

  • Теперь пришло время добавить немного кода. Имейте в виду, что с этой настройкой вам придется использовать <JavaVM/jni.h>. Обновите libnative.m, чтобы он выглядел следующим образом:

//
//  libnative.m
//  libnative
//
//  Created by maba on 2012-10-09.
//  Copyright (c) 2012 maba. All rights reserved.
//

#import "libnative.h"
#include <JavaVM/jni.h>

@implementation libnative

@end

#ifdef __cplusplus
extern "C" {
#endif

#ifndef VEC_LEN
#define VEC_LEN(v) (sizeof(v)/sizeof(v[0]))
#endif/*VEC_LEN*/

static JavaVM *javaVM;

static void print();

static JNINativeMethod Main_methods[] =
{
    { "print", "()V", (void*)print },
};

static struct {
    const char      *class_name;
    JNINativeMethod *methods;
    int             num_methods;
} native_methods[] = {
    { "com/stackoverflow/Main", Main_methods, VEC_LEN(Main_methods) },
};

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
    JNIEnv *env = 0;
    jclass cls  = 0;
    jint   rs   = 0;

    if ((*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_4)) {
        return JNI_ERR;
    }

    javaVM = jvm;

    for (unsigned int i = 0; i < VEC_LEN(native_methods); i++) {
        cls = (*env)->FindClass(env, native_methods[i].class_name);
        if (cls == NULL) {
            return JNI_ERR;
        }
        rs = (*env)->RegisterNatives(env, cls, native_methods[i].methods, native_methods[i].num_methods);
        assert(rs == JNI_OK);
    }

    return JNI_VERSION_1_4;
}

static void print(JNIEnv *env, jclass cls) {
    printf("Hello from C");
}

#ifdef __cplusplus
}
#endif
  • Соберите код, нажав +B.

  • А теперь пришло время создать код Java. Я просто создал класс Main в пакете com.stackoverflow.

com.stackoverflow.Main.java

package com.stackoverflow;

/**
 * @author maba, 2012-10-09
 */
public class Main {

    static native void print();

    static {
        System.out.println(System.getProperty("java.library.path"));
        System.loadLibrary("native");
    }

    public static void main(String[] args) {
        System.out.println("Loading native");
        Main.print();
    }
}
  • Установите точку останова на строке перед Main.print();. Запустите отладчик со следующей опцией JVM:

-Djava.library.path="/Users/maba/Library/Developer/Xcode/DerivedData/libnative-cquleqohzyhghnercyqdwpnznjdf/Build/Products/Debug/"

Эта строка немного длинная и зависит от пользователя. Вам придется самим искать имена каталогов, но они будут более или менее такими же, как у меня, за исключением сгенерированного пути libnative-cquleqohzyhghnercyqdwpnznjdf.

  • Программа должна быть запущена и ждать точки останова. Время подключить отладчик Xcode к работающему приложению.

  • Выберите меню Product -> Attach to Process > и укажите на запущенный процесс java в части System раскрывающегося списка. Если есть несколько процессов java, то это, скорее всего, тот, у которого самый высокий PID, но не всегда. Вам придется попробовать.

  • Создайте точку останова в коде c на строке printf("Hello from C");.

  • Вернитесь в Java IDE и продолжите выполнение с того места, где оно остановилось.

  • Вернитесь в Xcode и убедитесь, что он находится в точке останова!

В точке останова


Как я уже говорил ранее, это очень простой подход к obj-c/JNI, и ваш проект, вероятно, довольно большой, но с помощью этого небольшого тестового проекта вы можете, по крайней мере, увидеть, как он работает, а затем продолжить настройку своего собственного проекта.

09.10.2012
  • Просто чтобы вы знали, не имеет значения, выполняется ли отладка в Eclipse. Проблема заключалась в том, что у нас есть клиентский проект, который мы отлаживаем (он интегрируется с нашим программным обеспечением), а исполняемый файл представляет собой проект Java. Однако этот проект Java (в eclipse) использует библиотеку JNI, написанную на Objective C, для которой у нас есть проект в Xcode. Это проясняет? Нам все равно, как мы его отлаживаем, нам просто нужно иметь возможность пройти код JNI, а также структуру какао, чтобы увидеть, как они взаимодействуют с Speech API Mac OS X. 10.10.2012
  • @thatidiotguy Так что в этом случае у вас есть все для этого. Отладьте java-часть в eclipse и установите точку останова перед вызовом собственного метода. Из Xcode прикрепите к процессу java. Установите точку останова в собственном методе в Xcode. Продолжите выполнение в eclipse, и вы будете ждать точки останова JNI в Xcode. 11.10.2012

  • 2

    В прошлом, когда я работал с JNI, я создал тестовую систему, чтобы облегчить разработку нативной части приложения и кода JNI, который, как известно, легко испортить, избегая необходимости одновременной отладки с обеих сторон.

    Это было написано как собственное приложение, которое вызывает JVM программно, а не начинается с приложения Java, а затем пытается подключиться к JVM.

    Конечно, вы можете запустить это и отлаживать в Xcode, что гораздо предпочтительнее, чем Eclipse с CDT.

    Java-сторона этого механизма обычно довольно проста и несложна — в основном это метод, который вызывается из нативной части приложения, а затем делает один или несколько вызовов обратно в нативную часть через JNI.

    08.10.2012
  • Не могли бы вы предоставить подробную информацию о том, как бы вы настроили среду, чтобы код java выполнялся (по мере того, как он выполняет вызов JNI), но код c отлаживался? 08.10.2012
  • Я делал это на предыдущей работе, поэтому у меня больше нет доступа к исходному коду, чтобы точно рассказать вам, как я это сделал, однако этот Техническую заметку Apple. См. раздел Вызов виртуальной машины Java из собственного кода. Затем я использовал технику, описанную в разделе Вызов AWT/Swing из AppKit, для вызова JVM. 10.10.2012

  • 3

    Вот шаги, которые я выполняю для отладки JNI (C/C++) под Windows, я полагаю, что для ObjectiveC нужно то же самое. Для Linux это очень похоже (замените ; на :, %XXX% на ${XXX}...).

    1. Создайте файл с именем MyDebug.gdbinit.
    2. Добавьте в него эти 4 строки:

      set args -classpath .;xxxx.jar;yyy.jar путь.к.вашему.главному

      показать аргументы

      бегать

      bt

    3. запустить gdb и Java: gdb "%JAVA_HOME%\bin\java"

    4. Используйте графический интерфейс уровня Java, чтобы воспроизвести ошибку
    5. Если вы хотите шаг за шагом выполнять свой код JNI, gdb позволяет вам поставить несколько точек останова.
    13.10.2012

    4
  • Это проект для Mac OS X, использующий структуру какао. Это влияет на это? 04.10.2012
  • Собственный код находится в файле с расширением jnilib. Он включается через функциональность System.loadLibrary("libName"), поэтому загружается в JVM. 05.10.2012
  • Верно; поэтому вы захотите подключить gdb к любому процессу, который фактически запускает jvm. Затем используйте add-symobl-file в gdb, чтобы добавить символы для jni lib. Это должно работать, но может быть загнано в угол из-за странностей времени выполнения в JVM. 05.10.2012
  • Новые материалы

    5 проектов на Python, которые нужно создать прямо сейчас!
    Добро пожаловать! Python — один из моих любимых языков программирования. Если вы новичок в этом языке, перейдите по ссылке ниже, чтобы узнать о нем больше:

    Dall-E 2: недавние исследования показывают недостатки в искусстве, созданном искусственным интеллектом
    DALL-E 2 — это всеобщее внимание в индустрии искусственного интеллекта. Люди в списке ожидания пытаются заполучить продукт. Что это означает для развития креативной индустрии? О применении ИИ в..

    «Очень простой» эволюционный подход к обучению с подкреплением
    В прошлом семестре я посетил лекцию по обучению с подкреплением (RL) в моем университете. Честно говоря, я присоединился к нему официально, но я редко ходил на лекции, потому что в целом я нахожу..

    Освоение информационного поиска: создание интеллектуальных поисковых систем (глава 1)
    Глава 1. Поиск по ключевым словам: основы информационного поиска Справочная глава: «Оценка моделей поиска информации: подробное руководство по показателям производительности » Глава 1: «Поиск..

    Фишинг — Упаковано и зашифровано
    Будучи старшим ИТ-специалистом в небольшой фирме, я могу делать много разных вещей. Одна из этих вещей: специалист по кибербезопасности. Мне нравится это делать, потому что в настоящее время я..

    ВЫ РЕГРЕСС ЭТО?
    Чтобы понять, когда использовать регрессионный анализ, мы должны сначала понять, что именно он делает. Вот простой ответ, который появляется, когда вы используете Google: Регрессионный..

    Не зря же это называют интеллектом
    Стек — C#, Oracle Опыт — 4 года Работа — Разведывательный корпус Мне пора служить Может быть, я немного приукрашиваю себя, но там, где я живу, есть обязательная военная служба на 3..