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
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

liranke

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

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

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

打赏作者

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

抵扣说明:

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

余额充值