Java 可以从另一个本机方法调用一个本机方法吗?
我有一个Java类,它包含某些本机方法声明。它在finalize方法中包含对detroy()的调用,该方法现在已被弃用。作为最终确定的替代方案,我使用try with resources实现了AutoCloseable。但是问题是,AutoCloseable提供的close()方法必须在我的JSQ类中重写,它与我的代码中已经定义的现有本机close方法冲突。如果我能找到另一个可以调用destroy的地方,那就足够了。因此,我试图从本机close()调用destroy(),这是最后一个使用shdl的点。这是否可能/允许/建议?我没有删除或更改native close()的选项,这就是我试图从native close调用destroy的原因 JSQL.javaJava 可以从另一个本机方法调用一个本机方法吗?,java,java-native-interface,deprecated,function-call,finalize,Java,Java Native Interface,Deprecated,Function Call,Finalize,我有一个Java类,它包含某些本机方法声明。它在finalize方法中包含对detroy()的调用,该方法现在已被弃用。作为最终确定的替代方案,我使用try with resources实现了AutoCloseable。但是问题是,AutoCloseable提供的close()方法必须在我的JSQ类中重写,它与我的代码中已经定义的现有本机close方法冲突。如果我能找到另一个可以调用destroy的地方,那就足够了。因此,我试图从本机close()调用destroy(),这是最后一个使用shdl
class JSQ implements AutoCloseable{
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);
}
// to be removed
public void finalize()
{
destroy(shdl);
}
// alternative to finalize
@Override
public void close()
{
destroy();
}
protected void open()
{
parOpen (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 native void parOpen(long shdl);
// following method is called from sub-classes of JSQ
// super.close(shdl);
protected native void close(long shdl);
protected void execute() throws DhSQLException
{
parExec(shdl);
}
protected native void parExec(long shdl);
}
JSQ.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
status = SQ->SetStmt(cstmt);
return;
}
JNIEXPORT void JNICALL Java_com_project_package_JSQ_destroy
(JNIEnv *, jobject, jlong shdl)
{
delete SQ;
}
JNIEXPORT void JNICALL Java_com_project_package_JSQ_close
(JNIEnv *env, jobject, jstring jstmt, jlong shdl)
{
status_t status;
status = SQ->CloseSQ();
// Java_com_project_package_JSQ_destroy(shdl); ?
//destroy(shdl); ?
return;
}
Java_com_project_package_JSQ_destroy(shdl)
销毁(shdl)
或者可以用于删除finalize()并找到合适的销毁位置的任何其他替代方法?实际上允许从一个本地方法调用另一个本地方法。至少,我这样做时没有收到任何错误或警告。但调用必须包括任何本机方法预期的完整函数名,即
Java\u com\u project\u package\u JSQ\u destroy
,参数应包括:
Java_com_project_package_JSQ_destroy(env, <jobject_object_name>, shdl);
Java\u com\u项目\u包\u JSQ\u销毁(env,shdl);
它应该调用destroy方法。但是,它并不真正符合Java本机接口的目的,Java本机接口是一个允许Java代码调用并被其他语言编写的本机应用程序和库调用的层(这里是C++)。这种链接是合法的。在您的特定用例中,它应该是直接的 但总的来说,有一些问题不容忽视:
JNIEnv*
PushLocalFrame()
(并且在返回时不要忘记PopLocalFrame()
)ExceptionCheck()
或ExceptionOccurred()
来检查它,如果它必须继续调用另一个方法,也可以使用ExceptionClear()
。在被调用方返回后,调用方应谨慎地检查异常你为什么要使用本机代码?这是遗留代码,我对此无能为力。你是指这种方法吗?显然,不是。正如我所提到的,它是一种本机方法。方法定义在JSQ.cxx下提供。它只是在SQ上执行删除。这很好。请注意,
destroy
不会出现在Java堆栈跟踪应该生成一个Java异常。如果您也需要,那么您必须通过JNI调用该方法。