如上,我们已经编写好了CommandExecution.java,现在我们需要编译并生成c语言头文件。
完整的步骤如下:
cd ./javaweb-sec/javaweb-sec-source/javase/src/main/java/(换成自己本地的地址)。- vim或编辑器写入
./com/anbai/sec/cmd/CommandExecution.java文件(该目录已存了一个注释掉的CommandExecution.java取消掉代码注释就可以用了)。 javac -cp . com/anbai/sec/cmd/CommandExecution.java。javah -d com/anbai/sec/cmd/ -cp . com.anbai.sec.cmd.CommandExecution
注意JDK版本:
JDK10移除了javah,需要改为javac加-h参数的方式生产头文件,如果您的JDK版本正好>=10,那么使用如下方式可以同时编译并生成头文件。
javac -cp . com/anbai/sec/cmd/CommandExecution.java -h com/anbai/sec/cmd/
执行上面所述的命令后即可看到在com/anbai/sec/cmd/目录已经生成了CommandExecution.class和com_anbai_sec_cmd_CommandExecution.h了。
com_anbai_sec_cmd_CommandExecution.h:
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_anbai_sec_cmd_CommandExecution */#ifndef _Included_com_anbai_sec_cmd_CommandExecution#define _Included_com_anbai_sec_cmd_CommandExecution#ifdef __cplusplusextern "C" {#endif/** Class: com_anbai_sec_cmd_CommandExecution* Method: exec* Signature: (Ljava/lang/String;)Ljava/lang/String;*/JNIEXPORT jstring JNICALL Java_com_anbai_sec_cmd_CommandExecution_exec(JNIEnv *, jclass, jstring);#ifdef __cplusplus}#endif#endif
您可以使用IDE或者vim完成动态链接库的编写,如果您使用MacOS+CLion可能需要把#include <jni.h>改成#include "jni.h",不改也没关系,编译的时候带上库地址就行了。
头文件命名强制性
javah生成的头文件中的函数命名方式是有非常强制性的约束的,如Java_com_anbai_sec_cmd_CommandExecution_exec中Java_是固定的前缀,而com_anbai_sec_cmd_CommandExecution也就代表着Java的完整包名称:com.anbai.sec.cmd.CommandExecution,_exec自然是表示的方法名称了。(JNIEnv *, jclass, jstring)表示分别是JNI环境变量对象、java调用的类对象、参数入参类型。
如果您在不希望在命令行下编译lib,可以参考:Mac IDEA+CLION jni Hello World。
