JNI error Exception in thread "main" java.lang.UnsatisfiedLinkError: (Ljava/lang/String;)Ljava/lang/String;
JNI error Exception in thread "main" java.lang.UnsatisfiedLinkError: (Ljava/lang/String;)Ljava/lang/String;
我有一个本机方法可以显示给定路径的文件所有者。
public class ACL{
static {
System.loadLibrary("owner"); // hello.dll (Windows) or libhello.so (Unixes)
}
// Declare native method
private native String displayFileOwner(String path);
public static void main(String[] args) {
String str = "C:/Users/pradeep-pt3689/eclipse-workspace/Permission/jni/owner.c";
System.out.println(":"+new ACL().displayFileOwner(str));
}
}
在 运行
上显示此错误的代码
Exception in thread "main" java.lang.UnsatisfiedLinkError: ACL.displayFileOwner(Ljava/lang/String;)Ljava/lang/String;
at ACL.displayFileOwner(Native Method)
at ACL.main(ACL.java:10)
本机代码是:
#include <jni.h>
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include "ACL.h"
#include "accctrl.h"
#include "aclapi.h"
using namespace std;
JNIEXPORT jstring JNICALL Java_ACL_displayFileOwner(JNIEnv *env, jobject obj, jstring path)
{
jstring jstr=NULL;
const char *str=env->GetStringUTFChars(path, NULL);
DWORD dwRtnCode = 0;
PSID pSidOwner = NULL;
BOOL bRtnBool = TRUE;
LPTSTR AcctName = NULL;
LPTSTR DomainName = NULL;
DWORD dwAcctName = 1, dwDomainName = 1;
SID_NAME_USE eUse = SidTypeUnknown;
HANDLE hFile;
PSECURITY_DESCRIPTOR pSD = NULL;
// Get the handle of the file object.
hFile = CreateFile(
str,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
// Check GetLastError for CreateFile error code.
if (hFile == INVALID_HANDLE_VALUE) {
DWORD dwErrorCode = 0;
dwErrorCode = GetLastError();
jstr = env->NewStringUTF("CreateFile error.\n");
return jstr;
}
// Get the owner SID of the file.
dwRtnCode = GetSecurityInfo(
hFile,
SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION,
&pSidOwner,
NULL,
NULL,
NULL,
&pSD);
// Check GetLastError for GetSecurityInfo error condition.
if (dwRtnCode != ERROR_SUCCESS) {
DWORD dwErrorCode = 0;
dwErrorCode = GetLastError();
jstr = env->NewStringUTF("GetSecurityInfo error.\n");
return jstr;
}
// First call to LookupAccountSid to get the buffer sizes.
bRtnBool = LookupAccountSid(
NULL, // local computer
pSidOwner,
AcctName,
(LPDWORD)&dwAcctName,
DomainName,
(LPDWORD)&dwDomainName,
&eUse);
// Reallocate memory for the buffers.
AcctName = (LPTSTR)GlobalAlloc(
GMEM_FIXED,
dwAcctName);
// Check GetLastError for GlobalAlloc error condition.
if (AcctName == NULL) {
DWORD dwErrorCode = 0;
dwErrorCode = GetLastError();
jstr = env->NewStringUTF("GlobalAlloc error.\n");
return jstr;
}
DomainName = (LPTSTR)GlobalAlloc(
GMEM_FIXED,
dwDomainName);
// Check GetLastError for GlobalAlloc error condition.
if (DomainName == NULL) {
DWORD dwErrorCode = 0;
dwErrorCode = GetLastError();
jstr = env->NewStringUTF("GlobalAlloc error.\n");
return jstr;
}
// Second call to LookupAccountSid to get the account name.
bRtnBool = LookupAccountSid(
NULL, // name of local or remote computer
pSidOwner, // security identifier
AcctName, // account name buffer
(LPDWORD)&dwAcctName, // size of account name buffer
DomainName, // domain name
(LPDWORD)&dwDomainName, // size of domain name buffer
&eUse); // SID type
// Check GetLastError for LookupAccountSid error condition.
if (bRtnBool == FALSE) {
DWORD dwErrorCode = 0;
dwErrorCode = GetLastError();
if (dwErrorCode == ERROR_NONE_MAPPED)
jstr = env->NewStringUTF("Account owner not found for specified SID.\n");
else
jstr = env->NewStringUTF("Error in LookupAccountSid.\n");
return jstr;
} else if (bRtnBool == TRUE)
{// Print the account name.
jstr = env->NewStringUTF(AcctName);
env->ReleaseStringUTFChars(path, str);
}
return jstr;
}
我在 Web 项目中实际使用的相同 jni 方法来获取文本字段和打印所有者中的文件路径,效果非常好。
enter image description here
任何仍然面临这个问题的人。请尝试执行一个简单的 JNI HelloWorld 程序,看看它是否有效。在我的例子中,传递字符串和 returning 名称的程序工作得很好,而传递文件路径和 returning 所有者的相同方法类型不起作用。
JNIEXPORT jstring JNICALL Java_TestJNIString_sayHello(JNIEnv *env, jobject thisObj, jstring inJNIStr) {
const char *inCStr = (*env)->GetStringUTFChars(env, inJNIStr, NULL);
return (*env)->NewStringUTF(env, inCStr);
}
现在尝试添加不同的简单方法(如果有),在相同的 JNI 代码中使用上述方法,看看它是否有效。我有一个复杂的方法 returning 使用 return 类型字符串数组的文件的 ACL。我尝试执行一个不同的方法 returning 星期几作为字符串数组并且它有效。
现在执行上述 JNI 方法后,更改方法的逻辑但不更改 return 类型和参数传递。
这很奇怪,但确实有效。
我有一个本机方法可以显示给定路径的文件所有者。
public class ACL{
static {
System.loadLibrary("owner"); // hello.dll (Windows) or libhello.so (Unixes)
}
// Declare native method
private native String displayFileOwner(String path);
public static void main(String[] args) {
String str = "C:/Users/pradeep-pt3689/eclipse-workspace/Permission/jni/owner.c";
System.out.println(":"+new ACL().displayFileOwner(str));
}
}
在 运行
上显示此错误的代码Exception in thread "main" java.lang.UnsatisfiedLinkError: ACL.displayFileOwner(Ljava/lang/String;)Ljava/lang/String; at ACL.displayFileOwner(Native Method) at ACL.main(ACL.java:10)
本机代码是:
#include <jni.h>
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include "ACL.h"
#include "accctrl.h"
#include "aclapi.h"
using namespace std;
JNIEXPORT jstring JNICALL Java_ACL_displayFileOwner(JNIEnv *env, jobject obj, jstring path)
{
jstring jstr=NULL;
const char *str=env->GetStringUTFChars(path, NULL);
DWORD dwRtnCode = 0;
PSID pSidOwner = NULL;
BOOL bRtnBool = TRUE;
LPTSTR AcctName = NULL;
LPTSTR DomainName = NULL;
DWORD dwAcctName = 1, dwDomainName = 1;
SID_NAME_USE eUse = SidTypeUnknown;
HANDLE hFile;
PSECURITY_DESCRIPTOR pSD = NULL;
// Get the handle of the file object.
hFile = CreateFile(
str,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
// Check GetLastError for CreateFile error code.
if (hFile == INVALID_HANDLE_VALUE) {
DWORD dwErrorCode = 0;
dwErrorCode = GetLastError();
jstr = env->NewStringUTF("CreateFile error.\n");
return jstr;
}
// Get the owner SID of the file.
dwRtnCode = GetSecurityInfo(
hFile,
SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION,
&pSidOwner,
NULL,
NULL,
NULL,
&pSD);
// Check GetLastError for GetSecurityInfo error condition.
if (dwRtnCode != ERROR_SUCCESS) {
DWORD dwErrorCode = 0;
dwErrorCode = GetLastError();
jstr = env->NewStringUTF("GetSecurityInfo error.\n");
return jstr;
}
// First call to LookupAccountSid to get the buffer sizes.
bRtnBool = LookupAccountSid(
NULL, // local computer
pSidOwner,
AcctName,
(LPDWORD)&dwAcctName,
DomainName,
(LPDWORD)&dwDomainName,
&eUse);
// Reallocate memory for the buffers.
AcctName = (LPTSTR)GlobalAlloc(
GMEM_FIXED,
dwAcctName);
// Check GetLastError for GlobalAlloc error condition.
if (AcctName == NULL) {
DWORD dwErrorCode = 0;
dwErrorCode = GetLastError();
jstr = env->NewStringUTF("GlobalAlloc error.\n");
return jstr;
}
DomainName = (LPTSTR)GlobalAlloc(
GMEM_FIXED,
dwDomainName);
// Check GetLastError for GlobalAlloc error condition.
if (DomainName == NULL) {
DWORD dwErrorCode = 0;
dwErrorCode = GetLastError();
jstr = env->NewStringUTF("GlobalAlloc error.\n");
return jstr;
}
// Second call to LookupAccountSid to get the account name.
bRtnBool = LookupAccountSid(
NULL, // name of local or remote computer
pSidOwner, // security identifier
AcctName, // account name buffer
(LPDWORD)&dwAcctName, // size of account name buffer
DomainName, // domain name
(LPDWORD)&dwDomainName, // size of domain name buffer
&eUse); // SID type
// Check GetLastError for LookupAccountSid error condition.
if (bRtnBool == FALSE) {
DWORD dwErrorCode = 0;
dwErrorCode = GetLastError();
if (dwErrorCode == ERROR_NONE_MAPPED)
jstr = env->NewStringUTF("Account owner not found for specified SID.\n");
else
jstr = env->NewStringUTF("Error in LookupAccountSid.\n");
return jstr;
} else if (bRtnBool == TRUE)
{// Print the account name.
jstr = env->NewStringUTF(AcctName);
env->ReleaseStringUTFChars(path, str);
}
return jstr;
}
我在 Web 项目中实际使用的相同 jni 方法来获取文本字段和打印所有者中的文件路径,效果非常好。 enter image description here
任何仍然面临这个问题的人。请尝试执行一个简单的 JNI HelloWorld 程序,看看它是否有效。在我的例子中,传递字符串和 returning 名称的程序工作得很好,而传递文件路径和 returning 所有者的相同方法类型不起作用。
JNIEXPORT jstring JNICALL Java_TestJNIString_sayHello(JNIEnv *env, jobject thisObj, jstring inJNIStr) {
const char *inCStr = (*env)->GetStringUTFChars(env, inJNIStr, NULL);
return (*env)->NewStringUTF(env, inCStr);
}
现在尝试添加不同的简单方法(如果有),在相同的 JNI 代码中使用上述方法,看看它是否有效。我有一个复杂的方法 returning 使用 return 类型字符串数组的文件的 ACL。我尝试执行一个不同的方法 returning 星期几作为字符串数组并且它有效。
现在执行上述 JNI 方法后,更改方法的逻辑但不更改 return 类型和参数传递。
这很奇怪,但确实有效。