将本机 (C) 指针保留到对象实例中 - 并随后清理它
对于我的一个项目,我想为 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;
}
我在这里想要的是保留对 pamh 的引用 对于 PamHandle
的所有实例。这是怎么做到的?
编辑:好的,我已经有了答案,现在是清理部分:我是否使用 finalize()
调用本机清理方法,然后使用 super. Finalize();
,或者是否有一个由我可以/必须实现的 GC 触发的 JNI 函数?
For one of my projects, I want to implement a complete PAM implementation for Java (application side and module side as well).
Right now, I'm on the application side. I took jpam as a base but I stumble upon a problem, and after some hours of searching around I still cannot find the solution to my problem :/
This is the current code:
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;
}
What I want here is keep a reference to pamh
for all instances of PamHandle
. How is this done?
edit: OK, I have the answer to this, and now there's the cleanup part: do I use finalize()
to call a native cleanup method then super.finalize();
, or is there a JNI function which is triggered by the GC which I can/must implement?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用 long 来存储指向 pam_handle_t 的指针。
Java 端看起来像
当然你可以将其封装在一个类中,这样你就可以拥有接口。
C 端看起来像这样:
这将允许每个实例有一个 pam_handle_t。
每次手动传递整数比传递对象然后必须访问对象的字段的性能要高得多。
编辑
另外,如果您担心 jlong 无法正确保存指针,则 jlong 保证是 64 位的。因此,jlong 将一直适用于这种情况,直到我们开始获取 128 位整数(距离很远)。
Use a long to store a pointer to pam_handle_t.
Java-side it would look like
Of course you could encapsulate this inside a class, so you could have the interface.
C side it would look like this:
This would allow you to have one pam_handle_t per instance.
It is also alot more performant to manually pass the integer each time, rather than passing an object, and then having to access the object's field.
EDIT
Also, if you are worried about the jlong not being able to hold a pointer correctly, a jlong is guaranteed to be 64-bit. So, a jlong will work for this case all the way until we start getting 128-bit integers( a long long way away).
这里有两种情况:
目前,您的指针是函数的本地指针,不能在函数范围之外使用。请注意,如果所有新创建的函数都将通过一个函数调用,而该函数将通过您当前声明 pamh 的函数调用,那么您可以继续将指针作为函数参数传递。
但是,如果您的情况与上面提到的不同,那么您将必须使
pamh
glbal 以便它在程序的整个生命周期中保持有效,然后您可以在不同的函数中使用它。您必须声明
为全局变量。
请注意,使其全局化意味着您确保对它的访问是同步的,以防您的程序是多线程的。
There are two cases here:
Currently, Your pointer is local to the function and it cannot be used beyond the scope of the function. Note that if all your newly created functions will be called through a function which will be called through the function in which you currently declared
pamh
then you can just keep on passing the pointer as function parameters.However,If your case is not as mentioned above then you will have to make
pamh
glbal so that it remains valid throughout the life of the program and then you can use it accross different functions.You will have to declare,
as a global.
Note that making it global would mean you ensure access to it is synchronized in case your program is multithreaded.