正如Hovercraft Full Of Eels 已经建议的那样,您可以尝试使用单独的线程。我还会尝试添加更多 println 语句,以查明问题的原因。
为了重现您的问题,我在 Ubuntu 14.04 64 位上使用 Java SE 1.8.0_66-b17 (java -version) 和 gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4 (gcc --版本)。
为了简化一点,我没有将String 参数传递给hello 方法/函数,以暂时跳过该转换。这些是我用来测试的源文件:
// Test.java
import java.awt.Container;
import javax.swing.*;
public class Test extends JFrame {
private JPanel contentPane;
public static Container root;
/**
* Launch the application.
*/
public static void main(String[] args) {
try {
Test frame = new Test();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.callNativeFunction();
System.out.println("Test.main - before setting frame visible");
frame.setVisible(true);
System.out.println("Test.main - after setting frame visible");
} catch (Exception e) {
e.printStackTrace();
}
}
private void callNativeFunction() {
Thread nativeFunctionThread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Test.run - before calling hello.");
new JNIServer().hello(); // where hello is native method
System.out.println("Test.run - after calling hello.");
}
});
nativeFunctionThread.start();
}
}
// JNIServer.java
public class JNIServer {
public native void hello();
static {
System.out.println("Inload library");
System.loadLibrary("JNI_Lib");
}
}
// JNIServer.h (generated)
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JNIServer */
#ifndef _Included_JNIServer
#define _Included_JNIServer
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JNIServer
* Method: hello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_JNIServer_hello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
// JNI_Lib.c
#include <jni.h>
#include <stdio.h>
JNIEXPORT void JNICALL Java_JNIServer_hello(JNIEnv * environment,
jobject java_object) {
printf("Hello from C!\n");
}
为了构建应用程序,我运行了以下命令:
javac Test.java
java Test
javah JNIServer
gcc -fPIC -o libJNI_Lib.so -shared -I /usr/lib/jvm/java-8-oracle/include -I /usr/lib/jvm/java-8-oracle/include/linux JNI_Lib.c -lc
java -Djava.library.path=. Test
这是java -Djava.library.path=. Test 命令的输出:
Test.main - before setting frame visible
Test.run - before calling hello.
Inload library
Hello from C!
Test.run - after calling hello.
Test.main - after setting frame visible
万众瞩目的“来自 C 的你好!”被打印出来了。一个(非常小的)框架是可见的。 (您可以使用JFrame.setBounds 方法调整框架的大小和位置。)
编辑:使用 Eclipse
虽然应该可以合并Java and C project in Eclipse,但我建议从较小的步骤开始:使用两个单独的 Eclipse 项目(甚至更小:创建一个引用由 CLI C 项目创建的库的 Java 项目)。如果这样可行,您可以处理一个组合的 Eclipse 项目。
上面的 CLI 示例有 java.library.path 指向包含 libJNI_Lib.so 文件的目录。对于 Eclipse 中的 Java 项目,您可以选择 Run | Run Configurations... 菜单,如果需要,在左侧面板中选择 Java 项目,在右侧面板中选择 Arguments 选项卡,并添加“-Djava.library.path=”。 (不带引号)到 VM 参数。例如,请参阅运行配置对话框的屏幕截图: