Objective c 调试目标C JNI代码
情况如下: 我在eclipse中打开了一个客户机的java项目。它使用由Xcode Objective C项目创建的JNI库。当我执行Java代码时,有什么好方法可以调试eclipse中的C代码吗?显然,eclipse的默认调试器无法进入jni库文件,我们将丢失线程(这里的线程指的是调查线程,而不是编程线程) 任何建议或输入都是值得赞赏的,因为代码库足够大,遵循客户的代码将比其他选项快得多 谢谢 编辑:Objective c 调试目标C JNI代码,objective-c,xcode,eclipse,debugging,java-native-interface,Objective C,Xcode,Eclipse,Debugging,Java Native Interface,情况如下: 我在eclipse中打开了一个客户机的java项目。它使用由Xcode Objective C项目创建的JNI库。当我执行Java代码时,有什么好方法可以调试eclipse中的C代码吗?显然,eclipse的默认调试器无法进入jni库文件,我们将丢失线程(这里的线程指的是调查线程,而不是编程线程) 任何建议或输入都是值得赞赏的,因为代码库足够大,遵循客户的代码将比其他选项快得多 谢谢 编辑: 应该注意的是,jni库之所以用Objective-C编写,是因为它与MacOSX集成。它使用
应该注意的是,jni库之所以用Objective-C编写,是因为它与MacOSX集成。它使用Cocoa框架与Apple speech api集成。您可以从终端连接
gdb
(或lldb
)。如果使用本机代码启动进程是由fork()/exec()
--即,如果您不能键入gdb/some/command/line
--则您可能可以使用--waitfor
选项(参见手册页)等待进程启动
加载符号将很棘手
这是一个使用cocoa框架的MacOSX项目。这会影响你吗 这个 不应该。如果有什么不同的话,这将使它变得更容易,希望符号文件是一种可用的格式。关键通常是在java和本机代码之间的边界上找到合适的断点 是加载到JVM的动态库中的本机代码,还是您有一个在内部启动JVM的自定义可执行文件
在任何情况下,都需要将本机调试器附加到运行该本机代码的任何进程。可能在您适当地设置了基于java的调试会话之后。在过去进行JNI时,我已经构建了一个测试工具来促进应用程序的本机部分(以及JNI代码)的开发,这很容易出错,避免了从双方同时进行调试的需要 这是作为本机应用程序编写的,它以编程方式调用JVM,而不是从Java应用程序开始,然后尝试连接到JVM 当然,您可以启动它并在Xcode中调试它——这是使用CDT的Eclipse最好的体验
这种安排的Java端通常非常简单且不需要贡献——基本上是一种从应用程序的本机部分调用的方法,然后通过JNI将一个或多个调用返回到本机部分 我不确定我是否完全理解了您的设置,以及您是否需要从eclipse完成此操作。总之,我感兴趣的是使用JNI和Cocoa库编写一个小测试程序,什么都不做,只是为了调试obj-c/c代码 我成功地完成了这个设置并调试了代码。我对Java使用IntelliJ,对objc/c部分使用Xcode,但在eclipse中使用Java部分是不需要动脑筋的 所以您应该能够准确地设置我的项目结构并开始调试。从那里,您应该能够将这些知识应用到您自己更复杂的代码中 我是这样开始的:
- 通过选择Cocoa库在Xcode中创建一个新项目
- 将项目命名为
,并将其设置为动态类型libnative
- 为新项目选择一个地点。我使用
并跳过~/Development/
部分创建本地git…
- 这将在所选文件夹中创建一个名为
的新项目。已经自动创建了两个文件:lib native.xcodeproj
和libnative.h
libnative.m
- 首先,必须更改项目设置
部分中的Packaging
必须从Executable Extension
更改为dynlib
jnilib
- 必须更新
部分中的搜索路径
,以指向JNI框架:框架搜索路径
/System/Library/Frameworks/JavaVM.Framework/Frameworks/JavaNativeFoundation.Framework/
- 现在是添加一些代码的时候了。请注意,使用此设置时,您必须使用
。将
更新为如下代码:libnative.m
- 在
Main.print()之前的行上设置断点代码>。使用以下JVM选项启动调试器:
libnative cquleqohzyhghnercyqdwpnznjdf
路径外,它们或多或少与我的相同
- 程序应该在断点处运行并等待。将Xcode调试器附加到正在运行的应用程序的时间
- 选择菜单
->Product
,并指向下拉列表的Attach to Process>
部分中正在运行的System
进程。如果有多个java
进程,那么它很可能是PID最高的进程,但并不总是如此。你得试试java
- 在c代码中的
printf行(“Hello from c”)上创建一个断点代码>
- 返回JavaIDE并从停止的位置继续执行
- 回到Xcode,看看它在断点处等待
正如我前面所说的,这是一种非常简单的obj-c/JNI方法,您的项目可能相当大,但通过这个小测试项目,您至少可以看到它是如何工作的,然后继续自己的项目设置。以下是我在Windows下调试JNI(c/c++)的步骤,我认为ObjectiveC需要同样的步骤。对于Linux,它是
//
// 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
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();
}
}
-Djava.library.path="/Users/maba/Library/Developer/Xcode/DerivedData/libnative-cquleqohzyhghnercyqdwpnznjdf/Build/Products/Debug/"