noidon'tcare翻译口‍碑怎‍么‍样‍呢?

这样作不对,不过我找到正确的方法了,要用构造函数生成新的对象。 回复

能说说方法吗? 回复 更多评论

c的结构提里写有一个**p,指针的指针,在java中该如何封装??? 回复 更多评论

近遇到一个问题,请各位帮忙解决下:
这两个我理解应该是相同的吧,强制类型转换好像不启作用,应该如何转换呢?

JAVA的跨平台的特性深受java程 序员们的喜爱,但正是由于它为了实现跨平台的目的,使得它和本地机器的各种内部联系变得很少,大大约束了它的功能,比如与一些硬件设备通信,往往要花费很 大的精力去设计流程编写代码去管理设备端口,而且有一些设备厂商提供的硬件接口已经经过一定的封装和处理,不能直接使用java程序通过端口和设备通信,这种情况下就得考虑使用java程序去调用比较擅长同系统打交道的第三方程序,从 与他联系。

JNI编程系列之基础篇

最近干一个活需要从Java调用C++编译的动态链接库,研究了一下JNI,现在将网上搜罗的文档和自己的体会贡献出来。

JNI的做法是:通过在方法前加上关键字native来识别本地方法,然后用本地语言(如C,C++)来实现该方法,并编译成动态链接库,在Java的类中调用该动态链接库,然后就可以像使用Java自己的方法一样使用native方法了。这样做的好处是既具有了Java语言的便利性,又具有了C语言的效率;另一个好处是可以利用已有的C代码,避免重复开发。
下面从最简单的JNI程序入手,介绍如何进行JNI编程。

//设置classpath,如果程序用到了第三方的JAR包,也可以在这里面包含进来 //设置显示消息的类型,取值有gc、class和jni,如果一次取多个的话值之间用逗号格开,如-verbose:gc,class //该参数可以用来观察C++调用JAVA的过程,设置该参数后,程序会在标准输出设备上打印调用的相关信息 //选择一个根你安装的JRE版本最近的版本号即可,不过你的JRE版本一定要等于或者高于指定的版本号 //根据类的CLASS对象获取该类的实例 //获取类中的方法,最后一个参数是方法的签名,通过javap -s -p 文件名可以获得 //构造参数并调用对象的方法 //销毁虚拟机并释放动态库

???? c、JVM创建成功后,JNI_CreateJavaVM函数会传出一个JNI上下文环境对象(JNIEnv),利用该对象的相关函数就可以调用JAVA类的属性和方法了。

???? d、以上面的代码为例:先调用JNIEnv的FindClass方法,该函数传入一个参数,该参数就是java类的全局带包名的名称,如上面示例中的 test/Demo表示test包中的Demo类。这个方法会在你创建JVM时设置的classpath路径下找相应的类,找到后就会返回该类的 class对象。 Class是JAVA中的一个类,每个JAVA类都有唯一的一个静态的Class对象,Class对象包含类的相关信息。为了使FindClass方法能 找到你的类,请确保创建JVM时-Djava.class.path=参数设置正确。注意:系统环境变量中的CLASSPATH对这里创建JVM没有影 响,所以不要以为系统CLASSPATH设置好了相关路径后这里就不用设置了。

???? e、利用FindClass返回的class对象,调用GetMethodID函数可以获得里面方法的ID,在这里GetMethodID函数传入了三个 参数:第一个参数是class对象,因为方法属于某个具体的类;第二个参数是方法的名称;第三个参数是方法的签名,这个签名可以在前面3.3中介绍的方法 获得。

???? f、利用class对象,可以通过调用AllocObject函数获得该class对象对应类的一个实例,即Demo类的对象。

???? g、利用上面获取的函数ID和Demo类的对象,就可以通过CallObjectMethod函数调用相应的方法,该函数的参数跟printf函数的参数 一样,个数是不定的。第一个参数是类的对象;第二个参数是要调用的方法的ID;后面的参数就是需要传给调用的JAVA类方法的参数,如果调用的JAVA类 方法没有参数,则调用CallObjectMethod时传前两个参数就可以了。

???? h、从上面的示例中可以看到,在调用JAVA的方法前,构造传入的字符串时,用到了NewJString函数;在调用该方法后,对传出的字符串调用了 JstringToCString函数。这是由于Java中所有的字符都是Unicode编码,但是在本地方法中,例如用VC编写的程序,如果没有特殊的 定义一般都没有使用Unicode的编码方式。为了让本地方法能够访问Java中定义的中文字符及Java访问本地方法产生的中文字符串,定义了两个方法 用来做相互转换。

下面是一个使用该类的例子(真正跟用于演示的code很少,大部分都是些routine code,:)):

// 编码长度可以是1~3(据说理论上最长可以到6,不懂)。

直到Unicode 2.0,Unicode还是一个很简单的编码,每个字符16位——两个字节
到了Unicode 3.0,为了支持庞大的东亚象形文字,Unicode编码空间增加为0~10FFFF,提出代理对机制(用两个w_char存储一个图形字符)来支持10000~10FFFF之间的编码(这就是UTF-16的前身)

今天终于搞定困扰我一周的一个问题了。

我们的算法通过jni封装,在java调用的时候总是随机的crash掉,具体的位置在jvm里面,应该可以肯定是jvm做垃圾回收的时候死掉的。但是并不知道是在回收哪块内存出的问题,所以也就无从知道死的具体原因了。我们的程序是在jni层创建了一些java对象,然后返回给java层,大体结构像下面代码一样,我只能基本判断是我们的jni层在创建对象的时候(也就是createInfo函数)出问题了,至于具体什么问题,我也不清楚。

因为我对java不是很熟悉,所以只好一边学,一边弄。最初就是在local/glbal reference这些概念上下功夫,来回的读jni的specification,也没有发现自己的问题。后期又学着使用一些java的调试工具,比如jhat啊,hpjmeter啊,但是仍然没有什么头绪。上周一周,就在这个问题上不断的尝试,也没结果。

今天终于发现了问题所在,其实说来也很简单。jni要 创建的那些返回对象,是作为内部类定义的,所以在构造的时候需要传一个外层类实例才能初始化。也就是说,虽然看上去Info类的构造函数是无参数的,但实 际上它是有一个隐含参数的,相当于Info(Test outer)。如果在java层构造这个对象,那么outer参数会被自动传入,但我们在jni层构造,就需要自己传入这个参数了。如果没有给出这个参数,jni编译运行都没有问题,但实际上,它是用了一个未知的对象(就是在栈里面的一个随机值)来作为这个outer参数的,所以当这个对象需要释放的时候(一般也就是在垃圾回收的时候)就会crash了。

现在想起来,其实这个问题我原来曾经有过一次小遭遇,那时我在使用有参数构造函数来创建一个内部嵌套类,发现构造出来的对象值是错掉的。其实就是因为少传了一个outer参数啊,但是当时我没有去解决这个问题,而是绕过问题,采用构造函数无参数,然后在创建之后,再手工给每个数据字段赋值的方法。这样虽然表面上也达到了目的,但是隐藏了问题。

事实一次次的告诉我们,遇到问题一定要解决。就算你暂时绕过这个问题,但早晚它还会出来的。

我要回帖

更多关于 nocare 的文章

 

随机推荐