どのように正確にメモリ割り当てが行われているとどのようにJavaとCは同じオブジェクトを追跡するために相互作用していますか?

userAsh:

私は、long型のメンバ変数を含むクラスとネイティブメソッドの宣言のセットを持っています。私は、変数のメモリは、ネイティブメソッドのいずれかに割り当てられていると割り当て解除を破壊する別のネイティブメソッドを呼び出すことにより、ファイナライズ()メソッドに試みられていると信じています。私は、ファイナライズが廃止されていることを理解するが、前ファイナライズするための代替を見つけるために、私は、メモリの割り当てが起こって、どのようにJavaおよびCはJNIを通して同期を維持する方法と、この特定のメンバ変数が追跡されるかを理解する必要があります。私は、コードスニペットとのより良いシナリオを説明しようとします。

JSQ.java

class JSQ {
    protected long shdl;
    protected JSQ() { log("JSQ constructor"); }
    protected JSQ(String stmt, boolean isd)
        throws DhSQLException
    {
        // calls a set of native methods
        set_shdl();
        setstmt(stmt, shdl);
        setd(isd, shdl);
        prep(shdl);
    }

    public void finalize()
    {
        destroy(shdl);
    }

    private native void set_shdl() throws DhSQLException;
    private native void setstmt(String s, long shdl) throws DhSQLException;
    private native void setd(boolean b, long shdl);
    private native void prep(long shdl) throws DhSQLException;
    private native void destroy(long shdl);

    protected void execute() throws DhSQLException
    {
        parExec(shdl);
    }

    protected native void parExec(long shdl);
}

JSQL.cxx

#define SQ ((sq_stsm_t *)(shdl))

JNIEXPORT void JNICALL Java_com_project_package_JSQ_set_shdl
(JNIEnv *env, jobject obj_This)
{
    jclass cls;
    jmethodID mid;
    cls = (env)->GetObjectClass (obj_This);
    mid = (env)->GetMethodID (hThis,"set_JSQ_shdl","(J)V");

    status_t status;
    // memory allocation
    sq_stsm_t * S = new sq_stsm_t(status);
    if(status)
    {
        if (S) { delete S; }
        return;
    }
    // I understand that we're attempting to call a Java method from a native method.
    // But which method is it calling?
    // Also, are we converting S from sq_stms_t type to jlong?
    (env)->CallVoidMethod (obj_This,mid,(jlong) S);
    return;
}

JNIEXPORT void JNICALL Java_com_project_package_JSQ_setstmt
(JNIEnv *env, jobject, jstring jstmt, jlong shdl)
{
    status_t status;

    // cstmt is obtained using jstmt

    // Note: #define SQ ((sq_stsm_t *)(shdl))
    status = SQ->SetStmt(cstmt);

    return;
}

JNIEXPORT void JNICALL Java_com_project_package_JSQ_destroy
(JNIEnv *, jobject, jlong shdl)
{
    delete SQ;
}

私は混乱しているポイント:

  1. なぜ長いとjlong​​と長いへのユーザー定義型sq_stsm_tからの変換。私は、Javaがこのユーザー定義型を認識していないことを理解しています。しかし、なぜ長いの選択?

  2. なぜSQ上の#defineとどのように正確に破壊しないがSQに削除を呼び出すことによってset_shdlに割り当てられたメモリを削除しますか?

私が試し-と資源とのAutoCloseableは、はるかに、私の最良の選択肢であると結論しているために - ポストこれは、私はファイナライズの代替品を見つける必要があります。関連するネイティブ呼び出しがたくさんあるので、私はそれについて移動する方法をすると混同しています。しかし、それに対処するために別個の問題であると私はここでそれに行きたくありません。ただ、ユースケースのいくつかの背景を設定することに言及。

ヒラメ:

AのJava long変数は、あっても、64ビットシステムでは、アドレスを含むのに十分であり、64ビット幅であることが保証されます。キャストはlongC ++型システムの幸せを作ることだけがあります。ご覧のとおり、SQマクロが適切にポインタにこのアドレス背中を変換するために使用されるsq_stsm_tオブジェクト。

あなたの2番目の質問については:すべてのマクロは、いくつかのタイピング作業を取り除くされません。あなたのプログラムのJavaの部分は常に通過しますlong-typed shdlので、変数をSQマクロはちょうど実際に簡単にアクセス提供sq_stsm_tのオブジェクトを。

最後に、newそしてdelete:Cで一緒に行く++ new割り当てメモリをして、コンストラクタを呼び出し、deleteデストラクタを呼び出し、再びメモリを解放します。あなたのプロセスのメモリ使用量がこの後も同じままにすることができますので、「自由」とは、必ずしも、「戻ってOSに与える」という意味ではありませんのでご注意delete操作。

あなたのコード内のコメントについて:Java_com_project_package_JSQ_set_shdlJavaメソッドを呼び出そうとしboolean com.project.package.JSQ#set_JSQ_shdl(jlong)、それはあなたが貼り付けられたコードに存在しないものの、。私はそれがために、単純なセッターだと思いshdlフィールド?

実装は:あなたのフォローアップの計画についてはAutoCloseable良いアイデアです。あなたは、作成する必要がありますnative void close()呼び出して、あなたのJSQオブジェクトのメソッドdeletesq_stsm_tに格納されたオブジェクトshdlのフィールドを、次に置き換えるshdlとフィールドを(jlong)nullptr

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=333800&siteId=1
おすすめ