一、笔记

1.C调用Java中的方法,参考jni.pdf pg97
可以参考博文:http://blog.csdn.net/lhzjj/article/details/26470999
步骤:
  a. 创建java虚拟机
  b. 获得class
  c. 实例化对象:获得构造方法(方法名为“<init>”),构造函数,调用方法
  d. 调用方法:又分为获得方法,构造参数,调用方法。(对于静态方法不需要实例化对象,可以没有步骤c)

2.C读取修改Java类的对象的成员属性
  a. 获取属性ID
  b. 读取/设置

3.之前都是java JNIDemo手动启动java虚拟机执行java程序,若C程序中调用了
java程序需要调用函数JNI_CreateJavaVM()来自动启动java虚拟机。

4.由Java程序的class文件获取(JNI)函数签名
$ javap -p -s JNIDemo.class

5.在/usr/lib下也可也grep字符串:/usr/lib$ grep JNI_CreateJavaVM -r ./

6.Java中参数中的String类对应到C中的jstring类型

7.运行时报找不到某个动态库,可以设置此库的路径到LD_LIBRARY_PATH中

二、例子

Hello.java文件:

public class Hello {
private String name; /*C程序中调用SetObjectField()来设置*/
private int age; /*C程序中调用SetIntField()来设置*/ public static void main(String args[]) {
System.out.println("Hello, world!");
} public int sayhello_to(String name) {
System.out.println("Hello, "+name+"! I am "+this.name+", "+age+" years old.");
return 123;
} public static void sayhello_to() {
}
}

caller.c文件:

#include <stdio.h>
#include <jni.h> jint create_vm(JavaVM** jvm, JNIEnv** env)
{
JavaVMInitArgs args;
JavaVMOption options[1];
args.version = JNI_VERSION_1_6; /*创建1.6版本的java虚拟机*/
args.nOptions = 1;
options[0].optionString = "-Djava.class.path=./"; /*在当前目录下查找类*/
args.options = options;
args.ignoreUnrecognized = JNI_FALSE;
return JNI_CreateJavaVM(jvm, (void **)env, &args);
} int main(int argc, char **argv)
{
JavaVM* jvm;
JNIEnv* env; jclass cls;
int ret = 0; jmethodID mid;
jmethodID cid; jobject jobj;
jstring jstr; jfieldID nameID;
jfieldID ageID; int r; /* 1. create java virtual machine */
if (create_vm(&jvm, &env)) {
printf("can not create jvm\n");
return -1;
} /* 2. get class */
cls = (*env)->FindClass(env, "Hello"); /*获取Hello类对象*/
if (cls == NULL) {
printf("can not find hello class\n");
ret = -1;
goto destroy;
} /* 3. create object
* 3.1 get constructor method
* 3.2 create parameters
* 3.3 NewObject
* 注意:调用类的静态成员方法的时候不需要实例化对象
*/ /*<init>表示获取构造方法,构造函数的签名可以用javap -p -s Hello.class查看*/
/* Get the method ID for the String constructor */
cid = (*env)->GetMethodID(env, cls, "<init>", "()V");
if (cid == NULL) {
ret = -1;
printf("can not get constructor method");
goto destroy;
} /*调用类的构造函数实例化一个对象*/
jobj = (*env)->NewObject(env, cls, cid);
if (jobj == NULL) {
ret = -1;
printf("can not create object");
goto destroy;
} /* get/set field
* 1. get field id
* 2. get/set field
*/ /*设置Hello类对象的name属性,arg4是属性的签名*/
nameID = (*env)->GetFieldID(env, cls, "name", "Ljava/lang/String;");
if (nameID == NULL) {
ret = -1;
printf("can not get field name");
goto destroy;
}
jstr = (*env)->NewStringUTF(env, "Bill");
(*env)->SetObjectField(env, jobj, nameID, jstr); /*将name属性设置为“Bill”*/ /*设置Hello类对象的age属性*/
ageID = (*env)->GetFieldID(env, cls, "age", "I");
if (ageID == NULL) {
ret = -1;
printf("can not get field age");
goto destroy;
}
(*env)->SetIntField(env, jobj, ageID, 10); /* 4. call method
* 4.1 get method
* 4.2 create parameter
* 4.3 call method
*/ /*调用Java程序中的“sayhello_to”成员方法id*/
mid = (*env)->GetMethodID(env, cls, "sayhello_to","(Ljava/lang/String;)I");
if (mid == NULL) {
ret = -1;
printf("can not get method\n");
goto destroy;
} jstr = (*env)->NewStringUTF(env, "abcd@qq.com"); /*调用Java程序中的“sayhello_to”成员方法并获取返回值。
* 对比静态方法:
* 这里是CallIntMethod()且其参数是对象
* eg: static void main()是调用CallStaticVoidMethod()且参数是类
*/
r = (*env)->CallIntMethod(env, jobj, mid, jstr);
/*打印Java程序中的“sayhello_to”成员方法的返回值*/
printf("ret = %d\n", r); destroy: (*jvm)->DestroyJavaVM(jvm);
return ret;
}

测试运行:

javac Hello.java

javap -p -s Hello.class //获取成员函数和成员属性的Signature,在C中调用Java函数或设置类的属性的时候使用。

gcc -I/usr/lib/jvm/java-1.7.-openjdk-amd64/include/ -o caller caller.c -L /usr/lib/jvm/java--openjdk-amd64/jre/lib/amd64/server -ljvm

export LD_LIBRARY_PATH=/usr/lib/jvm/java--openjdk-amd64/jre/lib/amd64/server
./caller 运行结果:

$ ./caller
Hello, abcd@qq.com! I am Bill, 10 years old.
ret = 123

TODO: 看 jni.pdf

JNI学习笔记_C调用Java的更多相关文章

  1. JNI学习笔记_Java调用C —— 非Android中使用的方法

    一.学习笔记 1.java源码中的JNI函数本机方法声明必须使用native修饰. 2.相对反编译 Java 的 class 字节码文件来说,反汇编.so动态库来分析程序的逻辑要复杂得多,为了应用的安 ...

  2. 六、Android学习笔记_JNI_c调用java代码

    1.编写native方法(java2c)和非native方法(c2java): package com.example.provider; public class CallbackJava { // ...

  3. Android学习笔记_JNI_c调用java代码

    1.编写native方法(java2c)和非native方法(c2java): package com.example.provider; public class CallbackJava { // ...

  4. JNI学习笔记_Java调用C —— Android中使用的方法

    一.笔记 1.JNI(Java Native Interface),就是如何使用java去访问C/C++编写的那些库.若想深入了解JNI可以看官方文档jni.pdf.优秀博文:Android JNI知 ...

  5. 学习笔记(三)--->《Java 8编程官方参考教程(第9版).pdf》:第十章到十二章学习笔记

    回到顶部 注:本文声明事项. 本博文整理者:刘军 本博文出自于: <Java8 编程官方参考教程>一书 声明:1:转载请标注出处.本文不得作为商业活动.若有违本之,则本人不负法律责任.违法 ...

  6. JNI 学习笔记

    JNI是Java Native Interface的缩写,JNI是一种机制,有了它就可以在java程序中调用其他native代码,或者使native代码调用java层的代码.也 就是说,有了JNI我们 ...

  7. ndk学习18: JNI之C&C++调用Java

    一.Java反射机制 先了解Java反射机制原理 例子网上很多,反射很灵活 二. 在JNI层调Java 用途: Java层逆向比较容易,增加逆向门槛,把调用都写到JNI层,  让Java层无调用关系 ...

  8. Android(java)学习笔记167:Java中操作文件的类介绍(File + IO流)

    1.File类:对硬盘上的文件和目录进行操作的类.    File类是文件和目录路径名抽象表现形式  构造函数:        1) File(String pathname)       Creat ...

  9. 学习笔记(二)--->《Java 8编程官方参考教程(第9版).pdf》:第七章到九章学习笔记

    注:本文声明事项. 本博文整理者:刘军 本博文出自于: <Java8 编程官方参考教程>一书 声明:1:转载请标注出处.本文不得作为商业活动.若有违本之,则本人不负法律责任.违法者自负一切 ...

随机推荐

  1. OTU rank curve(Rank Abundance 曲线)【基本概念】

    16S结题报告中都会有这么一张图: 这张图是OTU Rank曲线,该曲线可以展示样品的多样性.而样品的多样性常通过以下两个方面进行解释:物种的丰富程度和均匀程度.Rank曲线中,曲线在横轴上的跨度越长 ...

  2. protected 与 internal

    protected:在当前类的“内部”  和  派生子类的“内部” 可访问(注意:实例对象不可访问 或者说 访问不到):如果静态,则在当前类内部和派生子类内部  具有“全局效果” internal:在 ...

  3. Johnny Solving CodeForces - 1103C (构造,图论)

    大意: 无向图, 无重边自环, 每个点度数>=3, 要求完成下面任意一个任务 找一条结点数不少于n/k的简单路径 找k个简单环, 每个环结点数小于n/k, 且不为3的倍数, 且每个环有一个特殊点 ...

  4. The Monster CodeForces - 917A (括号匹配)

    链接 大意:给定字符串, 只含'(',')','?', 其中'?'可以替换为'('或')', 求有多少个子串可以的括号可以匹配 (不同子串之间独立) 记$s_($为'('个数, $s_)$为')'个数 ...

  5. TCP/IP四层与OSI七层模型

      OSI七层和TCP/IP四层的关系 1.1 OSI引入了服务.接口.协议.分层的概念,TCP/IP借鉴了OSI的这些概念建立TCP/IP模型. 1.2 OSI先有模型,后有协议,先有标准,后进行实 ...

  6. HDU 1934 特殊数字

    有两种车牌号.让你判断第二种是不是在第一种之后且在第一种出Kth之前的车牌号. 本解中是把前面的字母看成一位十进制的数.自己是一个26或者21进制的数.如果比较时有两种.那么第一种和第一种的最后一个比 ...

  7. webservice 基本要点

    webservice的特点 webservices是自我包含的 webservices是自我描述的 webservices是跨平台和语言的 webservices是基于开放和标准的 webservic ...

  8. 若所有的参数皆需要类型转换——请为此采用non-member函数

    若所有的参数皆需要类型转换--请为此采用non-member函数 经常使用C++的程序猿(希望更多的程序媛),一般不会同意让classes支持类型转换,至于为什么,请看后续的博客.假如我们设计一个表示 ...

  9. cf935E

    题解: 树形dp 要记录一个最小的,一个最大的 然后转移 代码: #include<bits/stdc++.h> using namespace std; ; ][],f[N*][],T[ ...

  10. python关于时间的计算,time模块

    import time, datetime # time.time 返回当前时间的时间戳(1970纪元后经过的浮点秒数)(格林尼治时间). # 1分钟60秒,1小时3600秒,1天86400秒. pr ...