JNI编写详细步骤实践,javac编译,gcc编译

简介:

最近,使用native进行开发的工作有不少。本文进行native编程实践,将整个步骤以及注意事项做一个笔记。本次实践不使用任何集成开发编译环境,而是用最原始的文本编辑器+命令行的方式进行。

实例说明:

实现一个简单的jni调用,模拟“通过jni打印log日志,日志由java层传递给c层”。

开发步骤:

分成两大步骤来演示,一, java代码的编辑,编译,以及c头文件的生成;二,c语言代码的编辑,编译。

 1. java代码的编辑,编译,以及c头文件的生成:

1)java代码编辑:MyLog.java文件,内容如下:


public class MyLog {
	//获取c代码的日志
	native void outputLog(String str);
     
    static { System.loadLibrary("clog");}
     
    public static void main(String[] args) {
         MyLog a = new MyLog();
         a.outputLog("I from Java!!!");
         
    }
}

2)编译生成.class文件:

用javac命令编译即可:

aibook@aibookdeMacBook-Pro java_call_c % javac MyLog.java

aibook@aibookdeMacBook-Pro java_call_c % ls

MyLog.class MyLog.java

MyLog.class,就是java字节码文件。

3)生成头文件(.h文件):

用javah命令:

aibook@aibookdeMacBook-Pro java_call_c % javah MyLog

aibook@aibookdeMacBook-Pro java_call_c % ls

MyLog.class MyLog.h MyLog.java

其中,MyLog.h文件的内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class MyLog */

#ifndef _Included_MyLog
#define _Included_MyLog
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     MyLog
 * Method:    outputLog
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_MyLog_outputLog
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

2.  c语言代码的编辑,编译:

1)c语言代码:

新建立一个MyLog.c文件,内容如下:

#include "MyLog.h"
#include <stdio.h>

JNIEXPORT void JNICALL Java_MyLog_outputLog
  (JNIEnv *env, jobject obj,jstring str)
  {
    const char *cStr = (*env)->GetStringUTFChars(env, str, 0);
    printf("%s!\n", cStr);
    return;
  }

2)编译:编译c代码,用gcc命令将.c文件编译成一个.o:

gcc -I . -c MyLog.c

注意,可能出现如下问题:

fatal error: 'jni.h' file not found

#include <jni.h>

         ^~~~~~~

1 error generated.

显然,是找不到jni头文件的问题。我的解决办法是:

把jni相关的文件copy到自己当前目录,即和代码放在同一个目录下。

jni相关文件的来源:

/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/include/jni.h

/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/include/darwin/jni_md.h

运行完gcc -I . -c MyLog.c 命令后的目录文件:

MyLog.c        MyLog.h        MyLog.o        jni.h    jni_md.h        
MyLog.class    MyLog.java

3)链接:再将.o链接成一个lib库:

gcc -dynamiclib -o libclog.jnilib MyLog.o 

libclog.jnilib就是最后生成的nativelib库文件。

运行:

最后,运行结果如下:

MacBook-Pro java_call_c % java MyLog

I from Java!!!!

 运行的时候,有可能出现如下错误:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no clog in java.library.path

at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1860)

at java.lang.Runtime.loadLibrary0(Runtime.java:870)

at java.lang.System.loadLibrary(System.java:1122)

at MyLog.<clinit>(MyLog.java:6)

 

这是因为虽然库都有了,但是path没有指定。

我的解决方式是:直接在环境变量中指定,如下:

直接修改.bash_profile文件,在PATH环境变量中加入自己的编译目录。

PATH=$ndk:$JAVA_HOME/bin:$PATH:/Users/aaa/work/stu/c_stu/java_call_c

总结一下整个步骤:

1.编写java代码-->  2. javac编译成字节码 --> 3. javah生成c头文件-->

4.编写c代码--> 5.gcc编译c代码为.o文件 --> 6.gcc链接成lib库 -->

7. java运行


 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
GCC 是 C/C++ 编译器,不支持直接编译 Java 代码。Java 代码需要先被编译成字节码,然后由 Java 虚拟机(JVM)解释执行或者编译成本地代码执行。 Java 编译器通常使用 javac 命令进行编译。下面是一个简单的编译示例: ``` javac HelloWorld.java ``` 这将会编译名为 HelloWorld.javaJava 源代码文件,并生成一个名为 HelloWorld.class 的字节码文件。 如果你想使用 GCC 编译 Java 代码,你需要先将 Java 代码编译成字节码,然后再使用 GCC 编译字节码文件所生成的头文件和源文件。 下面是一个基本的步骤: 1. 使用 javac 命令编译 Java 代码文件: ``` javac HelloWorld.java ``` 2. 使用 javah 命令生成头文件: ``` javah HelloWorld ``` 这将生成一个名为 HelloWorld.h 的头文件。 3. 将头文件和字节码文件一起使用 JNI 编写 C 代码。在 C 代码中,你需要包含 Java 的头文件和 JNI 库,这样就可以调用 Java 方法了。 4. 使用 GCC 编译 C 代码: ``` gcc -c -I/usr/lib/jvm/java-8-openjdk-amd64/include -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux HelloWorld.c ``` 其中,-I 选项指定了 JavaJNI 的头文件所在的目录。 5. 使用 GCC 链接 C 代码和 Java 库: ``` gcc -shared -o libHelloWorld.so HelloWorld.o -lc -ljvm ``` 这将生成一个名为 libHelloWorld.so 的共享库,可以在 Java 中使用 System.loadLibrary() 方法加载。 需要注意的是,由于 GCC 不是专为编译 Java 代码而设计的,因此使用 GCC 编译 Java 代码可能会比较麻烦,并且可能会出现一些问题。建议还是使用专门的 Java 编译javac编译 Java 代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liranke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值