2011-12-22 25 views
3

ネットワークからバイナリデータを受け取るC++プログラムがあります。データが受信されると、C++からJavaクライアントへのバイト配列としてデータがコールバックされます。 SWIGのディレクター機能を使用して、コールバックのためにC++とJavaのクロス言語多型を簡単に実現します。ここにはa linkがあります。ディレクタを使用したC++とJava間のSWIG多型のメモリリーク

しかし、SWIGにchar *からJavaのbyte []に​​typemapsはありません。そこで、virous.iにパッチを追加しました。ここにはa linkがあります。

/*Director specific typemaps*/ 
%typemap(directorin, descriptor="[B") char *BYTE { 
    jbyteArray jb = (jenv)->NewByteArray(strlen(BYTE)); 
    (jenv)->SetByteArrayRegion(jb, 0, strlen(BYTE), (jbyte*)BYTE); 
    $input = jb; 
} 
%typemap(directorout) char *BYTE { 
$1 = 0; 
if($input){ 
     $result = (char *) jenv->GetByteArrayElements($input, 0); 
     if(!$1) 
      return $null; 
     jenv->ReleaseByteArrayElements($input, $result, 0); 
    } 
} 
%typemap(javadirectorin) char *BYTE "$jniinput" 
%typemap(javadirectorout) char *BYTE "$javacall" 

たとえば、私はJavaコードでバイト配列を受け取ることができます

class B extends A { 
    @Override 
    public void onDataReceived(byte[] data, long len) { 
     //handling the data. 
    } 
} 

が、それはそれを思わ:

class A{ 
public: 
     virtual void onDataReceived(const char* BYTE, const size_t len) {} 
}; 

を次にJavaコードで、私は拡張するために別のクラスBを持っている:私はC++でクラスが呼び出されJVMによってガベージコレクションされることはありません。 SWIGでonDataReceived方法は、ラッパーファイルを生成し、このようなものです:私のC++コードで

void SwigDirector_A::onDataReceived(char const *BYTE, size_t const len) { 
    JNIEnvWrapper swigjnienv(this); 
    JNIEnv * jenv = swigjnienv.getJNIEnv(); 
    jobject swigjobj = (jobject) NULL; 
    jbyteArray jBYTE = 0; 
    jlong jlen; 

    if (!swig_override[3]) { 
    A::onDataReceived(BYTE,len); 
    return; 
    } 
    swigjobj = swig_get_self(jenv); 
    if (swigjobj && jenv->IsSameObject(swigjobj, NULL) == JNI_FALSE) { 
    { 
     jbyteArray jb = (jenv)->NewByteArray(strlen(BYTE)); 
     (jenv)->SetByteArrayRegion(jb, 0, strlen(BYTE), (jbyte*)BYTE); 
     jBYTE = jb; 
    } 
    jlen = (jlong) len; 
    jenv->CallStaticVoidMethod(Swig::jclass_DataTransferJNI, Swig::director_methids[3], swigjobj, jBYTE, jlen); 
    if (jenv->ExceptionCheck() == JNI_TRUE) return; 
    } else { 
    SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null upcall object"); 
    } 
    if (swigjobj) jenv->DeleteLocalRef(swigjobj); 
} 

コールバックが行われた後、私は受信バッファ内のデータを削除します。しかし、私はJava VisualVMから、Javaクライアントプロセスで使用されているメモリがGC-edでないことを長い間確認しました。助けてくれてありがとう!

PS。データはかなり大きく、約32KBです。

+0

Directorタイプマップのjbへの参照を削除して解決しました。(jenv) - > DeleteLocalRef(jb); – Qinjin

+0

あなたは答えとしてそれを書いて、受け入れられたとマークするべきです。その解決法はコメントとしてしか生きられないほど重要です。 – Flexo

答えて

2

Directorタイプマップのjbへの参照を削除して解決しました。(jenv) - > DeleteLocalRef(jb);

ここにはupdated patchがあります。

関連する問題