gpt4 book ai didi

java - 将 native (C) 指针保存到对象实例中——然后清理它

转载 作者:太空宇宙 更新时间:2023-11-04 06:40:45 25 4
gpt4 key购买 nike

对于我的一个项目,我想为 Java 实现一个完整的 PAM 实现(应用程序端和模块端)。

现在,我在应用程序方面。我以 jpam 作为基础,但我偶然发现了一个问题,经过几个小时的搜索,我仍然找不到解决问题的方法:/

这是当前代码:

JNIEXPORT jint JNICALL Java_org_eel_kitchen_pam_PamHandle_authenticate(
JNIEnv *pEnv, jobject pObj, jstring pServiceName, jstring pUsername,
jstring pPassword, jboolean debug)
{
pam_handle_t *pamh = NULL;
int retval;

/*
* TODO: unclear, see what's what
*
* With my first tests, it appears that GetStringUTFChars() makes the JVM
* crash if memory cannot be allocated... But an array copy was made. See
* what happens if the JVM decides NOT to make a copy. Right now it is
* assumed that allocations succeed. And the JNI spec says
* GetStringUTFChars() does NOT throw an OOM on failure.
*/
service_name = (*pEnv)->GetStringUTFChars(pEnv, pServiceName, NULL);
username = (*pEnv)->GetStringUTFChars(pEnv, pUsername, NULL);
password = (*pEnv)->GetStringUTFChars(pEnv, pPassword, NULL);

/* Get a handle to a PAM instance */
retval = pam_start(service_name, username, &PAM_converse, &pamh);

if (retval != PAM_SUCCESS) {
pr_debug("pam_start failed for service %s: %s\n", service_name,
pam_strerror(NULL, retval));
goto out_nohandle;
}

pam_set_item(pamh, PAM_AUTHTOK, password);
retval = pam_authenticate(pamh, 0);

/* Is user permitted access? */
if (retval != PAM_SUCCESS) {
pr_debug("failed to authenticate user %s: %s\n", username,
pam_strerror(NULL, retval));
goto out_free;
}

retval = pam_acct_mgmt(pamh, 0);

if (retval != PAM_SUCCESS)
pr_debug("failed to setup account for user %s: %s\n", username,
pam_strerror(NULL, retval));

out_free:
/* Clean up our handles and variables */
if (pam_end(pamh, retval) != PAM_SUCCESS) {
pamh = NULL;
pr_debug("Fuchs! Failed to release PAM handle\n");
}

out_nohandle:
(*pEnv)->ReleaseStringUTFChars(pEnv, pServiceName, service_name);
(*pEnv)->ReleaseStringUTFChars(pEnv, pUsername, username);
(*pEnv)->ReleaseStringUTFChars(pEnv, pPassword, password);

return retval;
}

我在这里想要的是为 PamHandle 的所有实例保留对 pamh 的引用。这是怎么做到的?

编辑:好的,我有了答案,现在是清理部分:我是否使用 finalize() 调用 native 清理方法然后 super.finalize();,或者是否有一个由我可以/必须实现的 GC 触发的 JNI 函数?

最佳答案

使用 long 来存储指向 pam_handle_t 的指针。

Java 端它看起来像

long handle = Pam.create();
Pam.DoSomething(handle,arg1,arg2);

当然你可以将它封装在一个类中,这样你就可以拥有接口(interface)。

PamHandle p = new PamHandle();
p.DoSomething(arg1,arg2);

C 端看起来像这样:

JNIEXPORT jlong JNICALL Java_org_Create(
JNIEnv *pEnv)
{
pam_handle_t *pamh = createNew pam_handle somehow
jlong result = (jlong) pamh;
return result;
}

JNIEXPORT jint JNICALL Java_org_Blah_Blah_blah(
JNIEnv *pEnv, jlong handle, jstring arg1,jstring arg2)
{
pam_handle_t *pamh = (pam_handle_t*)handle;
// ... Do rest of stuff
}

这将允许您在每个实例中拥有一个 pam_handle_t。每次都手动传递整数,而不是传递一个对象,然后必须访问该对象的字段,性能也会提高很多。

编辑

此外,如果您担心 jlong​​ 无法正确保存指针,jlong​​ 保证是 64 位的。因此,jlong​​ 将一直适用于这种情况,直到我们开始获得 128 位整数(还有很长的路要走)。

关于java - 将 native (C) 指针保存到对象实例中——然后清理它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8544917/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com