JNI基础java、C++交互

来源:互联网 发布:c语言aes加密 分段 编辑:程序博客网 时间:2024/04/28 00:34
 老大让做一个用于前台页面调用硬件设备的程序,因为是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 __cplusplusextern "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,顺利执行了,然后,然后就没有然后了。

0 0