参考:https://www.cnblogs.com/andyliu1988/p/6041542.html
https://blog.csdn.net/shensky711/article/details/52806794
软件环境:
- ubuntu14.04
- eclipse
- clion
一、java代码
在eclipse中新建Test工程,package为test,创建Demo类。Demo.java如下。
package test;
public class Demo {
//用于演示如何访问静态的基本类型属性
public static int COUNT = 8;
//演示对象型属性
private String msg;
private int[] counts;
public Demo() { this("缺省构造函数"); }
//演示如何访问构造器
public Demo(String msg) { this.msg = msg; this.counts = null; }
public String getMessage() { return msg; }
//该方法演示如何访问一个静态方法
public static String getHelloWorld() { return "Hello world!"; }
//该方法演示参数的传入传出及中文字符的处理
public String append(String str, int i) { return str + i; }
// 演示数组对象的访问
public int[] getCounts() { return counts; }
//演示如何构造一个数组对象
public void setCounts(int[] counts) { this.counts = counts; }
// 演示异常的捕捉
public void throwExcp()throws IllegalAccessException
{
throw new IllegalAccessException("exception occur.");
}
}
二、C++代码
在clion中新建一个demo1工程,main.cpp如下:
#include <jni.h>
#include <string>
#include <iostream>
#include <memory.h>
using namespace std;
char* jstringToChar(JNIEnv* env, jstring jstr) {
char* rtn = NULL;
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("utf-8");//GB2312中文乱码
jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
jsize alen = env->GetArrayLength(barr);
jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
if (alen > 0)
{
rtn = (char*) malloc(alen + 1);
memcpy(rtn, ba, alen);
rtn[alen] = 0;
}
env->ReleaseByteArrayElements(barr, ba, 0);
return rtn;
}
jstring charTojstring(JNIEnv* env, const char* pat) {
//定义java String类strClass
jclass strClass = (env)->FindClass("Ljava/lang/String;");
// 获取String(byte[],String)的构造器,用于将本地byte[]数组转换为一个新String
jmethodID ctorID = (env)->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
//建立byte数组
jbyteArray bytes = (env)->NewByteArray(strlen(pat));
// 将char* 转换为byte数组
(env)->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*) pat);
// 设置String, 保存语言类型,用于byte数组转换至String时的参数
jstring encoding = (env)->NewStringUTF("utf-8");
// 将byte数组转换为java String,并输出
return (jstring) (env)->NewObject(strClass, ctorID, bytes, encoding);
}
int main() {
char opt1[] = "-Djava.compiler=NONE"; /** 暂时不知道啥意思,网上抄来的 */
char opt2[] = "-Djava.class.path=/home/hl/eclipse-workspace/Test/bin"; /** 指定Java类编译后.class文件所在的目录 */
char opt3[] = "-verbose:NONE"; /** 暂时不知道啥意思,网上抄来的 */
JavaVMOption options[3];
options[0].optionString = opt1; options[0].extraInfo = NULL;
options[1].optionString = opt2; options[1].extraInfo = NULL;
options[2].optionString = opt3; options[2].extraInfo = NULL;
JavaVMInitArgs jargv;
jargv.version = JNI_VERSION_1_6; /** JDK JNI VERSION*/
jargv.nOptions = 3;
jargv.options = options;
jargv.ignoreUnrecognized = JNI_TRUE;
JavaVM* jvm = NULL;
JNIEnv* jenv = NULL;
//创建虚拟机
jint res = JNI_CreateJavaVM( &jvm, (void**)&jenv, &jargv );
if ( res < 0 )
return -1;
//查找java类
jclass cls = jenv->FindClass("test/Demo");
if ( NULL == cls ) {
if( jenv->ExceptionOccurred() )
jenv->ExceptionDescribe();
else {
std::cout << "jc null" << std::endl;
}
return 1;
}
//调用静态方法 public static String getHelloWorld() { return "Hello world!"; }
jmethodID mid = jenv->GetStaticMethodID(cls, "getHelloWorld","()Ljava/lang/String;");
jstring msg = (jstring)jenv->CallStaticObjectMethod(cls, mid);
cout<<jstringToChar(jenv, msg)<<endl;
//调用静态属性 public static int COUNT = 8;
jfieldID fid = jenv->GetStaticFieldID(cls, "COUNT","I");
int count = (int)jenv->GetStaticIntField(cls, fid);
cout<<count<<endl;
//演示参数的传入传出及中文字符的处理 public String append(String str, int i) { return str + i; }
jobject obj = jenv->AllocObject(cls);
jmethodID mid1 = jenv->GetMethodID(cls, "append","(Ljava/lang/String;I)Ljava/lang/String;");
//构造参数并调用对象的方法
const char szTest1[] = "苹果";
jstring arg1 = charTojstring(jenv, szTest1);
jstring msg1 = (jstring) jenv->CallObjectMethod(obj, mid1, arg1, 12);
cout<<jstringToChar(jenv, msg1)<<endl;
//调用构造函数public Demo(String msg) { this.msg = msg; this.counts = null;}
jmethodID mid2 = jenv->GetMethodID(cls,"<init>","(Ljava/lang/String;)V");
const char szTest2[] = "电信";
jstring arg2 = charTojstring(jenv, szTest2);
jobject demo = jenv->NewObject(cls,mid2,arg2);
//验证是否构造成功 public String getMessage() { return msg; }
mid2 = jenv->GetMethodID(cls, "getMessage","()Ljava/lang/String;");
jstring msg2 = (jstring)jenv->CallObjectMethod(demo, mid2);
cout<<jstringToChar(jenv, msg2)<<endl;
//传入传出数组
//构造数组
int arrayCpp[] = {1,3,5,7,9};
jintArray array = jenv->NewIntArray(5);
jenv->SetIntArrayRegion(array, 0, 5, arrayCpp);
//传入数组 public void setCounts(int[] counts) { this.counts = counts; }
jobject obj1 = jenv->AllocObject(cls);
jmethodID mid3 = jenv->GetMethodID(cls,"setCounts","([I)V");
jenv->CallVoidMethod(obj1, mid3, array);
//获取数组 public int[] getCounts() { return counts; }
mid3 = jenv->GetMethodID(cls,"getCounts","()[I");
jintArray msg3 = (jintArray)jenv->CallObjectMethod(obj1, mid3, array);
int len =jenv->GetArrayLength(msg3);
jint* elems =jenv-> GetIntArrayElements(msg3, 0);
for(int i=0; i< len; i++)
{
cout<<"ELEMENT "<<i<<" IS "<<elems[i]<<endl;
}
jenv->ReleaseIntArrayElements(msg3, elems, 0);
//异常处理 public void throwExcp()throws IllegalAccessException { throw new IllegalAccessException("exception occur."); }
jobject obj2 = jenv->AllocObject(cls);
jmethodID mid4 = jenv->GetMethodID(cls,"throwExcp","()V");
jenv->CallVoidMethod(obj2, mid4);
//获取异常信息
string exceptionInfo = "";
jthrowable excp = 0;
excp = jenv->ExceptionOccurred();
if(excp)
{
jclass cls = jenv->GetObjectClass(excp);
jenv->ExceptionClear();
jmethodID mid5 = jenv->GetMethodID(cls, "toString","()Ljava/lang/String;");
jstring msg = (jstring) jenv->CallObjectMethod(excp, mid5);
cout<<jstringToChar(jenv, msg)<<endl;
jenv->ExceptionClear();
}
std::cout << "Hi , this is a c++ project!" << std::endl;
return 0;
}
CMakelists.txt如下:
cmake_minimum_required(VERSION 3.8)
project(demo1)
set(CMAKE_CXX_STANDARD 11)
include_directories("/usr/local/java/jdk-9/include" "/usr/local/java/jdk-9/include/linux")
link_directories(/usr/local/java/jdk-9/lib/server )
set(SOURCE_FILES main.cpp)
add_executable(demo1 ${SOURCE_FILES})
target_link_libraries(
demo1
jvm
)
运行结果如下所示:
/home/hl/CLionProjects/demo1/cmake-build-debug/demo1
Hello world!
8
苹果12
电信
ELEMENT 0 IS 1
ELEMENT 1 IS 3
ELEMENT 2 IS 5
ELEMENT 3 IS 7
ELEMENT 4 IS 9
java.lang.IllegalAccessException: exception occur.
Hi , this is a c++ project!
Process finished with exit code 0