2019-01-10 c调用jar包填坑记录

2022-05-13 08:35:06 浏览数 (1)

折腾了两天总算搞定c调用jar包,其中遇到的问题这里总结一下: 1、起始demo 参考C调用java例子先跑起来 2、开发环境 使用linux虚拟机效率很低,找到了gnuwin32实现在windows下运行Makefile,使用的是https://sourceforge.net/projects/gnuwin32/ ,只需要把 mingw32-make.exe文件改名为make.exe 3、java开发 直接使用eclipse生成一个mvn项目,以这个最简项目开始入手 使用mvn编译出jar给c调用,参考maven将所有的依赖打成一个包,确保依赖没有问题,验证方法:

代码语言:javascript复制
java -cp mytest.jar com.test.mytest.App

能够执行成功(jar复制到c文件同一个目录,不成功估计是第7条的问题) 4、jar的调用 options.optionString ="-Djava.class.path=.;mytest.jar"; 这个参数里面的分号不能搞错,否则总是找不到java的类 5、java函数返回值只能是string 其他类型一定得不到返回值,只好老老实实把其他类型转换为string返回 6、java函数执行异常返回值也拿不到 好的习惯是给java代码增加try catch,并且打印异常错误,从而能够快速发现问题,否则就是干着急也看不出问题在哪里,5和6两个问题基本耗费了我一天时间才解决 7、jvm.dll找不到的问题 直接把jvm.dll所在的路径添加到path就可以了 8、如果异常出现并显示java的crash堆栈 估计是函数的参数传递错误了,或者少传参数了 9、linux下和windows的区别有两个 编译命令要改一下:

代码语言:javascript复制
gcc -I/usr/lib/jvm/jdk1.8.0_111/include -I/usr/lib/jvm/jdk1.8.0_111/include/linux -o hello_world hello_world.c -L/usr/lib/jvm/jdk1.8.0_111/jre/lib/amd64/server -ljvm -D__int64="long long" 

另外c代码里面改一句话

代码语言:javascript复制
options.optionString ="-Djava.class.path=.;mytest.jar";

修改为:

代码语言:javascript复制
options.optionString ="-Djava.class.path=.:mytest.jar";

这里附上c的代码,java代码就自己脑补

代码语言:javascript复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include<jni.h>

JNIEnv* create_vm(JavaVM **jvm)
{
    JNIEnv* env;
    JavaVMInitArgs args;
    JavaVMOption options;
    args.version = JNI_VERSION_1_6;
    args.nOptions = 1;
    options.optionString ="-Djava.class.path=.;mytest.jar";
    args.options = &options;
    args.ignoreUnrecognized = 0;
    int rv;
    rv = JNI_CreateJavaVM(jvm,(void**)&env, &args);
    if (rv < 0 || !env)
        printf("Unable to Launch JVM%dn",rv);
    else
        printf("Launched JVM! :)n");
    return env;
}


void invoke_class(JNIEnv* env)
{
    jclass clazz;
    jmethodID main_method;
    jmethodID square_method;
    jmethodID power_method;
    jint number=20;
    jint exponent=3;
    clazz =(*env)->FindClass(env, "com/test/mytest/App");
    if(clazz == NULL) {
        printf("can't find hello_world_class");
        return;
    }
    // 这里调用main
    main_method =(*env)->GetStaticMethodID(env, clazz, "main","([Ljava/lang/String;)V");
    if(main_method == NULL) {
        printf("can't find main_methodn");
        return;
    }
    (*env)->CallStaticVoidMethod(env,clazz, main_method, NULL);

    // 这里调用public static String abiEncode(String abi, String data)
    jstring str = (*env)->NewStringUTF(env,"{ "constant":false,  "inputs":[{"name":"i","type":"int"},  {"name":"s","type":"string"},  {"name":"j","type":"int"}],  "name":"f4",  "outputs":[{"name":"i","type":"int"},  {"name":"s","type":"string"},  {"name":"j","type":"int"}],  "type":"fallback" }");
    printf("jstring strn");

        jstring str2 = (*env)->NewStringUTF(env,"111, "aaa", 222");
    printf("jstring str2n");

    jmethodID abiEncode_method =
    (*env)->GetStaticMethodID(env, clazz, "abiEncode","(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");

    if (abiEncode_method == NULL) {
        printf("can't find abiEncode_methodn");
        return; /* method not found */
    }


    jstring result = (*env)->CallStaticObjectMethod(env, clazz, abiEncode_method,str,str2);
    printf("jbyteArray arr %xn",result);
    if (result == NULL) {
        printf("can't call abiEncode_methodn");
        return; /* method not found */
    }
    const char *message = (*env)->GetStringUTFChars(env, result, NULL);
    if (NULL == message) return;
    printf("In C, the returned string is %sn", message);
    (*env)->ReleaseStringUTFChars(env, result, message);

        (*env)->DeleteLocalRef(env,str2);
        (*env)->DeleteLocalRef(env,str);
        (*env)->DeleteLocalRef(env,clazz);
        
}


int main(int argc,char **argv)
{
    JavaVM *jvm;
    JNIEnv *env;
    env = create_vm(&jvm);
    if(env == NULL)
        return 1;
    invoke_class(env);
    return 0;
}

如果不用Makefile就直接用下面的命令编译:

代码语言:javascript复制
gcc -I"C:/Program Files/Java/jdk1.8.0_101/include/" -I"C:/Program Files/Java/jdk1.8.0_101/include/win32" -o hello_world hello_world.c -L"C:/Program Files/Java/jdk1.8.0_101/jre/bin/server" -ljvm -D__int64="long long"

0 人点赞