私は、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;
}
私は混乱しているポイント:
なぜ長いとjlongと長いへのユーザー定義型sq_stsm_tからの変換。私は、Javaがこのユーザー定義型を認識していないことを理解しています。しかし、なぜ長いの選択?
なぜSQ上の#defineとどのように正確に破壊しないがSQに削除を呼び出すことによってset_shdlに割り当てられたメモリを削除しますか?
私が試し-と資源とのAutoCloseableは、はるかに、私の最良の選択肢であると結論しているために - ポストこれは、私はファイナライズの代替品を見つける必要があります。関連するネイティブ呼び出しがたくさんあるので、私はそれについて移動する方法をすると混同しています。しかし、それに対処するために別個の問題であると私はここでそれに行きたくありません。ただ、ユースケースのいくつかの背景を設定することに言及。
AのJava long
変数は、あっても、64ビットシステムでは、アドレスを含むのに十分であり、64ビット幅であることが保証されます。キャストはlong
C ++型システムの幸せを作ることだけがあります。ご覧のとおり、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_shdl
Javaメソッドを呼び出そうとしboolean com.project.package.JSQ#set_JSQ_shdl(jlong)
、それはあなたが貼り付けられたコードに存在しないものの、。私はそれがために、単純なセッターだと思いshdl
フィールド?
実装は:あなたのフォローアップの計画についてはAutoCloseable
良いアイデアです。あなたは、作成する必要がありますnative void close()
呼び出して、あなたのJSQオブジェクトのメソッドdelete
にsq_stsm_t
に格納されたオブジェクトshdl
のフィールドを、次に置き換えるshdl
とフィールドを(jlong)nullptr
。