您的位置:首页 > 编程语言 > C语言/C++

JNI基础java、C++交互

2016-02-26 17:58 411 查看
 老大让做一个用于前台页面调用硬件设备的程序,因为是java公司,第一个想到便是Applet,由它做为前台页面程序。

          最简单的applet

         那么,先做一个applet Demo.本人不懂这个,一开始以为又会是一番艰辛,不过接触之后,再一次被java的强大所感动,太简单了,做完了一点成就感都没有。下面是java代码:

        
class nHello extends {
public void paint(Graphics g){
g.drawString("Hello Applet",50,50);
}
}


 

        很犀利吧,很难相信这点代码就可以做到什么,但它就是做到了。 现在把它嵌到网页就好了,HTML代码:

 
<html>
<body>
<applet id="applet" code="nHello.class" width="500" height="300"/>
</body>
</html>


 然后把html和class放在同一目录下,浏览器打开,根据你的安全设置,会有不同提示,一般IE默认会提示是不安装Activex控件,同意即可,Firefox则没有提示,直接就运行了.

 

applet和JavaScript合体
 js调用applet是比较简单的,只要是java的publice方法,js都可以直接调用。js代码如下:

var applet = document.getElementById("applet");
applet.hello();

 java代码如下:
public void hello(){
System.out.println("Hello java");
}  

其实Javascript和Applet交互就这么简单(注意,这里是JavaScript调用Applet,不是Applet调用JS.关于Applet中调用JS,可自己搜索相关资料).

如果hello()有返回值的话,JS还可以接受返回值。

最简单的JNI

牛逼的技术出来了,那就是JNI!这个其实也只是技术本身很牛逼,做起来还是很简单,下面在原有的java代码上添加一段:

static{
System.loadLiberary("nHello");
}
public native void hello();


Java要做的就这么多,具体的实现就交给C++了(我用的是VC6.0)

第一步生成class文件 javac nHello.java

第二部生成C++引用的头文件javah nHello.java 生成文件内容如下
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class nHello */
#ifndef _Included_nHello
#define _Included_nHello
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: nHello
* Method: hello
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_nHello_hello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif



这里我们只关心那个方法,把方法copy到下面的c++source file里面

第三部具体的C++代码实现.

新建dll工程->新建c++ source file,下面是实现代码:
#include <stdio.h>
#include <jni.h>
#include <nHello.h>
//从Hello.h拷贝来的
JNIEXPORT void JNICALL Java_nHello_hello
(JNIEnv *, jobject){
printf("Hello C++");


不用怀疑c++代码就这么简单,但是jni.h和Hello.h的路径要设置正确,编译器才能找到这两个文件

jni.h在jdk/include下

jni.h里面还会包含一个jni_md.h,在jdk/include/win32目录下

nHello.h就随便你放了

把以上提到的路径加到C++的库目录下.工具->选项->目录.

然后编译dll,就会生成我们需要的dll文件.

这个dll的文件名,就是我们在java代码中System.loadLiberary("nHello")里面的这个参数,大小写无所谓,后缀名不需要,会自动识别。

System.loadLiberary()这个方法会默认搜索几个目录,把dll放在正确的目录下,JVM就能自动加载了.然后我们的native就能运行了。

java nHello,控制台输入

Hello C++;

Applet和JNI合体

上面我们的JNI是没有在applet环境下运行的,下面就要把Applet和JNI结合起来了。

java代码
import java.awt.*;
import java.applet.*;
public class nHello extends Applet{
public void init(){
System.loadLibrary("nHello");
}

public static native String hello();

public String nHello(){
return "Hello,Java "+hello();
}
}
 C++代码

#include <stdio.h>
#include "nHello.h"
JNIEXPORT jstring JNICALL Java_nHello_hello
(JNIEnv *jenv, jobject jobj)
{
return jenv->NewStringUTF("Hello,C++");
}
Java Script代码
var applet = document.getElementById("applet");
alert("Hello,JavaScript "+applet.nHello());

这里几个主要的代码就这样,至于其他次要的工作,就不再一一赘述.

到了这里我们发现,由于Applet是在客户端运行的,那么我们如何把我们的dll也放到客户端呢.

首先,试试把class文件和dll打包一起发到客户端行不行呢,jar -cvf nHello.jar *.class *.dll.注意,打包的话<applet>标签里面就要加个archive属性,archive="nHello.jar".

打开浏览器,结果失败了,同志们就不要再试了。

那么最简单的方法,就是手动拷贝到客户端,把我们的dll拷贝到system32下.也可以放入服务器bin目录下,据说可以自动跟着applet下载安装,没试过,不清楚。

再打开浏览器运行,如果前面步骤都没问题的话,浏览器应该会报access denied错误.紧要关头,突现离奇错误,为虾米呢?请听下文分解.

applet数字签名

其实动动脚指头就能想得通了,为了安全,applet不可能具有肆无忌惮的权限,想读就读,想写就写,那样网络世界就乱套了。applet默认的安全机制是阻止对客户端的任何操作的(必须阻止).那我们就要想办法允许applet有读写权限。又接着去网上查了许多资料,发现有的人说可以读写,有的人说不能(我的心凉了一半啊,都进行到这一步了,我容易吗我),但是不管怎样,只要还有希望,就要继续努力.按照网友们给出的方法,对applet的jar包签名.

首先把.class都打成jar包:jar -cvf nHello.jar *.class

然后用jdk/bin目录下的keytool生成.store文件:keytool -genkey -keystore nHello.store -alias Mission -validity 999.这样会提示你输入一些信息,最后时候确认即可.

最后用jdk/bin下的jarsigner给jar文件签名 jarsigner -verbose -keystore nHello.store iccard.jar Mission.会提示你输入密码,然后会打印出签名的过程(verbose参数的作用).

关于applet签名的过程,可以去百度“applet签名”,由于以上只凭记忆写的,所以难免有不准的地方。

好了,这下我们的jar包可厉害了,它已经不是一般的jar包了,它是一个签过名的jar包,一个具有对客户端读写权限的jar包.好了,现在让我们满怀期待的打开浏览器,嗯,IE提示是否允许Active,允许,然后就跳出窗口让我们验证签名,允许。。然后,OMG,顺利执行了,然后,然后就没有然后了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: