<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    悟心

    成功不是將來(lái)才有的,而是從決定去做的那一刻起,持續(xù)累積而成。 上人生的旅途罷。前途很遠(yuǎn),也很暗。然而不要怕。不怕的人的面前才有路。

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      93 隨筆 :: 1 文章 :: 103 評(píng)論 :: 0 Trackbacks

    原文出處

    JNI之C++調(diào)用Java類(lèi) —— java.lang.String

        為什么要用C++調(diào)用Java類(lèi)?很難回答,寫(xiě)著文章只是覺(jué)得JNI很有意思。于是開(kāi)始編寫(xiě)一段使用VC++在Windows系統(tǒng)里調(diào)用java的String類(lèi),在C++里調(diào)用String類(lèi)內(nèi)的一些方法。

        JNI已經(jīng)被開(kāi)發(fā)了很多年,而在我2年多的Java編程時(shí)間里從來(lái)沒(méi)有接觸過(guò)。直到最近研究JVM實(shí)現(xiàn)原理才注意到JNI。 JNI既Java Native Interface,Native這個(gè)詞我見(jiàn)過(guò)我認(rèn)為最恰當(dāng)?shù)姆g就是原生。原生的意思就是來(lái)自系統(tǒng)自己的,原汁原味的東西,例如Win32 API。Java類(lèi)需要在虛擬機(jī)上運(yùn)行,也就不是原生的,同樣.NET Framework也不是原生的。JNI也就是Java原生接口。關(guān)于JNI的規(guī)范,以及為什么要使用它,它能做些什么,都在http://java.sun.com/j2se/1.4.2/docs/guide/jni/spec/jniTOC.html里記述著。

        JNI是規(guī)范,它規(guī)定了虛擬機(jī)的接口,而把具體的實(shí)現(xiàn)留給開(kāi)發(fā)者。

        JVM的實(shí)現(xiàn)不是唯一的,目前存在很多種Java虛擬機(jī),Sun Hotspot,IBM JDK,還有HP的,Kaffe等等。最流行的就是Sun的Hotspot,最復(fù)雜的就是IBM JDK,這是IBM的一貫作風(fēng)。本文不討論JVM的實(shí)現(xiàn),只關(guān)注JNI。如果您安裝了Sun的JDK,您就能在[JAVA_HOME]\include目錄下找到j(luò)ni.h。這個(gè)頭文件就是虛擬機(jī)的唯一接口,你可以調(diào)用它聲明的函數(shù)創(chuàng)建一個(gè)JVM。

        在說(shuō)明C++調(diào)用Java類(lèi)之前,我想先演示一下如果編寫(xiě)Java Native Method。

    1.編寫(xiě)帶有Native方法的Java類(lèi)

    package org.colimas.jni.test;

    public class JniTest {

        static { System.loadLibrary("JniTestImpl"); }  //JVM調(diào)用JniTestImpl.dll

        public JniTest(){
        }

        //原生方法
        public native void print(String str);

        /**
        * @param args
        */
        public static void main(String[] args) {
                JniTest test=new JniTest();
                test.print("hello JVM"); //調(diào)用原生方法
        }
    }

    2.使用javah生成c語(yǔ)言頭文件。

    javah -jni org.colimas.jni.test.JniTest

    目錄里多了一個(gè)org_colimas_jni_test_JniTest.h文件,打開(kāi)文件,內(nèi)容如下:

    /* DO NOT EDIT THIS FILE - it is machine generated */

    #include <jni.h>

    /* Header for class org_colimas_jni_test_JniTest */


    #ifndef _Included_org_colimas_jni_test_JniTest
    #define _Included_org_colimas_jni_test_JniTest
    #ifdef __cplusplus

    extern "C" {

    #endif

    /*
     * Class:     org_colimas_jni_test_JniTest
     * Method:    print
     * Signature: (Ljava/lang/String;)V
     */

    JNIEXPORT void JNICALL Java_org_colimas_jni_test_JniTest_print
      (JNIEnv *, jobject, jstring);

    #ifdef __cplusplus
    }

    #endif
    #endif


    其中的Java_org_colimas_jni_test_JniTest_print就是JniTest類(lèi)里面的print原生方法的C語(yǔ)言聲明。

    3.編寫(xiě)C代碼實(shí)現(xiàn)原生方法print

    #include <jni.h>
    #include "org_colimas_jni_test_JniTest.h" //javah生成的頭文件
    #include <stdio.h>

    JNIEXPORT void JNICALL Java_org_colimas_jni_test_JniTest_print
      (JNIEnv *env, jobject object,jstring str)
    {
           //獲得字符串
           const char * txt=(*env)->GetStringUTFChars(env,str,0);
           printf("%s\n",txt); //打印到控制臺(tái)
           return;
    }


    參數(shù)JNIEnv *env,是JNI里最重要的變量。Java.exe創(chuàng)建JVM,之后JVM生成一個(gè)env,該env相當(dāng)于JVM內(nèi)的Session,可以完成創(chuàng)建Java對(duì)象,調(diào)用類(lèi)方法,獲得類(lèi)的屬性等等。

    在這里env將方法的參數(shù)Str從JNI的jstring類(lèi)型轉(zhuǎn)換為常數(shù)char數(shù)組。

    4.編譯

    cl  /Ic:\j2sdk1.4.2_10\include /Ic:\j2sdk1.4.2_10\include\win32 /c  JniTestImpl.c

    5.連接為DLL

    link /dll JniTestImpl.obj

    6.設(shè)置PATH

    set PATH=C:\MyProject\Colimas\CD\JNI\MyJNI;%PATH%

    7.運(yùn)行

    java org.colimas.jni.test.JniTest

    返回結(jié)果

    hello JVM

    結(jié)束

        以上是實(shí)現(xiàn)Java原生方法的開(kāi)發(fā)過(guò)程,下面進(jìn)入正題,使用C++調(diào)用Java的java.lang.String類(lèi)。

    1. Object類(lèi)出創(chuàng)建JVM。

    使用Java類(lèi)之前必須要?jiǎng)?chuàng)建JVM環(huán)境。JDK由java.exe來(lái)完成。本文有Object類(lèi)的靜態(tài)方法BeginJVM來(lái)創(chuàng)建,用EndJVM來(lái)關(guān)閉。

    創(chuàng)建JVM之后會(huì)在創(chuàng)建2個(gè)變量,分別是JNIEnv* env和JavaVM* jvm,JNIEnv上文已經(jīng)說(shuō)明,JavaVM,顧名思義,代表Java虛擬機(jī),用它來(lái)關(guān)閉JVM。

    Object類(lèi)的頭文件

    #include "jni.h"

    class Object
    {
    public:
        static bool BeginJVM();
        static bool EndJVM();
        Object();
        virtual ~Object();

    protected:
        static JNIEnv* env;
        static JavaVM* jvm;
    };

    object.cpp代碼

    #include "stdafx.h"
    #include "JavaClasses.h"
    #include "Object.h"

    Object::Object()
    {}

    Object::~Object()
    {}

    JNIEnv* Object::env=NULL;
    JavaVM* Object::jvm=NULL;

    //創(chuàng)建JVM

    bool Object::BeginJVM()
    {

        JavaVMOption options[3];
        JavaVMInitArgs vm_args;

        //各種參數(shù)
        options[0].optionString="-Xmx128m";
        options[1].optionString="-Verbose:gc";
        options[2].optionString="-Djava.class.path=.";

        vm_args.version=JNI_VERSION_1_2;
        vm_args.options=options;
        vm_args.nOptions=3;

        //創(chuàng)建JVM,獲得jvm和env
        int res = JNI_CreateJavaVM(&jvm,(void **)&env, &vm_args);
        return true;
    }

    bool Object::EndJVM()
    {
        //關(guān)閉JVM
        jvm->DestroyJavaVM();
        return true;
    }

    2. C++的String類(lèi)調(diào)用java.lang.String類(lèi)方法

    編寫(xiě)C++版的String類(lèi),調(diào)用java String類(lèi)方法。調(diào)用的方法如下:

        String  replaceAll(String regex, String replacement);

        boolean endsWith(String str);

        int indexOf(String str);

        int compareTo(String anotherString);

        char charAt(int i);

    String的頭文件:

    class String  :public Object
    {
    public:
    //與要調(diào)用的Java方法名一致。
        const char * replaceAll(char *regex,char *replacement);

        bool endsWith(char * str);

        int indexOf(char * str);

        int compareTo(char *anotherString);

        char charAt(int i);

        String(char *str);

        virtual ~String();
    };

    實(shí)現(xiàn):

    #include "stdafx.h"
    #include "String.h"
    #include "jni.h"

    using namespace std;

    jclass clazz;    //全局變量,用來(lái)傳遞class
    jobject object;  //全局變量,用來(lái)傳遞object
    String::String(char *str)
    {
        jstring jstr;

        if (Object::env ==NULL){
            cout << "JVM is not created" << endl;
            exit(-1);
        }

        //獲得java.lang.String類(lèi)
        clazz=Object::env->FindClass("java/lang/String");

        if (clazz ==0 ){
            cout << "Class is not found" << endl;
            exit(-1);
        }

        //獲得String(String str)構(gòu)造體
        jmethodID mid= Object::env->GetMethodID(clazz,"<init>", "(Ljava/lang/String;)V");

        if (mid==0){
            cerr<< "GetMethodID Error for class" << endl;
            exit(-1);
        }

        //將字符串封裝為jstring。
        jstr = Object::env->NewStringUTF(str);

        if (jstr == 0) {
            cerr << "Out of memory" <<endl;
            exit(-1);
        }

        cout << "invoking method" << endl;

        //創(chuàng)建一個(gè)java.lang.String對(duì)象。
        object=Object::env->NewObject(clazz,mid,jstr);
    }

    String::~String()
    {}

    char String::charAt(int i)
    {
        if (Object::env ==NULL){
            cout << "JVM is not created" << endl;
            exit(-1);
        }

        if (clazz ==0 ){
            cout << "Class is not found" << endl;
            exit(-1);
        }

        if (object ==0 ){
            cout << "String object is not created" << endl;
            exit(-1);
        }

        jmethodID mid;

        //獲得charAt方法,(I)C表示 參數(shù)為int型,返回char型。詳細(xì)參見(jiàn)JNI規(guī)范
        mid = Object::env->GetMethodID(clazz,"charAt", "(I)C");

        if (mid==0){
            cerr<< "GetMethodID Error for class" << endl;
            exit(-1);
        }

        jint ji=i;

        cout << "invoking method" << endl;

        //調(diào)用charAt
        jchar z = Object::env->CallCharMethod(object,mid,i);

        //返回結(jié)果。
        return z;
    }


    int String::compareTo(char *anotherString)
    {

        if (Object::env ==NULL){
            cout << "JVM is not created" << endl;
            exit(-1);
        }

        if (clazz ==0 ){
            cout << "Class is not found" << endl;
            exit(-1);
        }

        if (object ==0 ){
            cout << "String object is not created" << endl;
            exit(-1);
        }

        jmethodID mid;

        //(Ljava/lang/String;)I表示參數(shù)為java.lang.String,返回int
        mid= Object::env->GetMethodID(clazz,"compareTo", "(Ljava/lang/String;)I");

        if (mid==0){
            cerr<< "GetMethodID Error for class" << endl;
            exit(-1);
        }

        jstring jstr = Object::env->NewStringUTF(anotherString);
        cout << "invoking method" << endl;

        //調(diào)用方法
        jint z=Object::env->CallIntMethod(object,mid,jstr);

        //返回結(jié)果
        return z;
    }


    int String::indexOf(char *str)
    {
        if (Object::env ==NULL){
            cout << "JVM is not created" << endl;
            exit(-1);
        }

        if (clazz ==0 ){
            cout << "Class is not found" << endl;
            exit(-1);
        }

        if (object ==0 ){
            cout << "String object is not created" << endl;
            exit(-1);
        }

        jmethodID mid;
        mid= Object::env->GetMethodID(clazz,"indexOf", "(Ljava/lang/String;)I");

        if (mid==0){
            cerr<< "GetMethodID Error for class" << endl;
            exit(-1);
        }

        jstring jstr = Object::env->NewStringUTF(str);
        cout << "invoking method" << endl;

        jint z=Object::env->CallIntMethod(object,mid,jstr);
        return z;
    }


    bool String::endsWith(char *str)
    {

        if (Object::env ==NULL){
            cout << "JVM is not created" << endl;
            exit(-1);
        }

        if (clazz ==0 ){
            cout << "Class is not found" << endl;
            exit(-1);
        }

        if (object ==0 ){
            cout << "String object is not created" << endl;
            exit(-1);
        }

        jmethodID mid;
        mid= Object::env->GetMethodID(clazz,"endsWith", "(Ljava/lang/String;)Z");

        if (mid==0){
            cerr<< "GetMethodID Error for class" << endl;
            exit(-1);
        }

        jstring jstr = Object::env->NewStringUTF(str);
        cout << "invoking method" << endl;

        bool z = Object::env->CallBooleanMethod(object,mid,jstr);
        return z;
    }


    const char * String::replaceAll(char *regex, char *replacement)
    {
        if (Object::env ==NULL){
            cout << "JVM is not created" << endl;
            exit(-1);
        }

        if (clazz ==0 ){
            cout << "Class is not found" << endl;
            exit(-1);
        }

        if (object ==0 ){
            cout << "String object is not created" << endl;
            exit(-1);
        }

        jmethodID mid;
        mid= Object::env->GetMethodID(clazz,"replaceAll", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");

        if (mid==0){
            cerr<< "GetMethodID Error for class" << endl;
            exit(-1);
        }

        jvalue array[2];
        jstring jreg = Object::env->NewStringUTF(regex);
        jstring jstr = Object::env->NewStringUTF(replacement);

        array[0].l=jreg;
        array[1].l=jstr;

        cout << "invoking method" << endl;

        //傳入?yún)?shù),調(diào)用replaceAll方法
        jobject z=Object::env->CallObjectMethodA(object,mid,array);
        const char *result=Object::env->GetStringUTFChars((jstring)z, 0);

        return (const char *)result;
    }

    3.測(cè)試

    編寫(xiě)測(cè)試代碼

    using namespace std;

    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    {
        int nRetCode = 0;

        if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)){
            cerr << _T("Fatal Error: MFC initialization failed") << endl;
            nRetCode = 1;
        } else{
            //創(chuàng)建JVM
            Object::BeginJVM();

            String test("hello");

            //調(diào)用replaceAll
            const char *result = test.replaceAll("l","z");

            //返回結(jié)果
            cout<< result <<endl;

            //關(guān)閉JVM
            Object::EndJVM();
        }
        return nRetCode;
    }


    4.運(yùn)行

    編譯需要 jni.h和jvm.lib文件。

    jni.h在[JAVA_HOME]\include

    jvm.lib在[JAVA_HOME]\lib

    運(yùn)行需要jvm.dll

    jvm.dll在[JAVA_HOME]\ jre\bin\client

    運(yùn)行結(jié)果如下:

    invoking method

    invoking method

    hezzo

    Press any key to continue

    盡管本文的代碼很有意思,但我還沒(méi)有想到有什么價(jià)值,以及應(yīng)用到實(shí)際項(xiàng)目中的理由。


    本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/onlymilan/archive/2006/07/20/947652.aspx

    posted on 2009-11-18 11:01 艾波 閱讀(3119) 評(píng)論(1)  編輯  收藏 所屬分類(lèi): ApplicationJava

    評(píng)論

    # re: JNI之C++調(diào)用Java類(lèi) —— java.lang.String[未登錄](méi) 2013-03-18 09:18 a
    感覺(jué)挺有意思的,先大略看了一下。回頭再仔細(xì)研究一下 ,里面感覺(jué)能挖出一些很有價(jià)值的東西  回復(fù)  更多評(píng)論
      

    主站蜘蛛池模板: 91福利免费体验区观看区| 亚洲中文字幕成人在线| 亚洲午夜福利AV一区二区无码| 亚洲AV成人无码久久WWW| 亚洲一区二区三区写真| 中文字幕免费高清视频| 亚洲春色在线观看| 性做久久久久久免费观看| 亚洲国产精品ⅴa在线观看| 中文字幕视频免费在线观看 | 国产免费看JIZZ视频| 亚洲人成网站18禁止久久影院| 亚洲国产精品久久久久秋霞小| 国产美女精品视频免费观看 | 在线观看肉片AV网站免费| 亚洲成人精品久久| 91九色精品国产免费| 亚洲国产精品无码久久九九大片 | 水蜜桃亚洲一二三四在线| 国产a视频精品免费观看| 亚洲精品字幕在线观看| 无码成A毛片免费| 亚洲日本va在线观看| 国产成人免费手机在线观看视频| 国产午夜亚洲精品不卡| 中文字幕精品亚洲无线码二区 | 国产一级淫片a视频免费观看| 国产精品免费在线播放| 国产精品视频免费一区二区| 亚洲高清在线视频| 亚洲一级在线观看| 99热精品在线免费观看| 亚洲人成网亚洲欧洲无码久久| 日韩插啊免费视频在线观看| 天天爽亚洲中文字幕| 亚洲成av人在片观看| 国产免费丝袜调教视频| 一级片在线免费看| 亚洲三级在线播放| 亚洲中文久久精品无码| 欧美好看的免费电影在线观看|