JNI error Exception in thread "main" java.lang.UnsatisfiedLinkError: (Ljava/lang/String;)Ljava/lang/String;

huangapple go评论61阅读模式
英文:

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));
    }
}
#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;
}
英文:

I have a native method that displays the file owner for a given path.

public class ACL{
static {
System.loadLibrary(&quot;owner&quot;); // hello.dll (Windows) or libhello.so (Unixes)
}
// Declare native method
private native String displayFileOwner(String path);
public static void main(String[] args) {
String str = &quot;C:/Users/pradeep-pt3689/eclipse-workspace/Permission/jni/owner.c&quot;;
System.out.println(&quot;:&quot;+new ACL().displayFileOwner(str));
}
}

The code showing this error on running

> 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)

The native code is:

#include &lt;jni.h&gt;
#include &lt;iostream&gt;
#include &lt;windows.h&gt;
#include &lt;tchar.h&gt;
#include &quot;ACL.h&quot;
#include &quot;accctrl.h&quot;
#include &quot;aclapi.h&quot;
using namespace std;
JNIEXPORT jstring JNICALL Java_ACL_displayFileOwner(JNIEnv *env, jobject obj, jstring path)
{
jstring jstr=NULL;
const char *str=env-&gt;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-&gt;NewStringUTF(&quot;CreateFile error.\n&quot;);
return jstr;
}
// Get the owner SID of the file.
dwRtnCode = GetSecurityInfo(
hFile,
SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION,
&amp;pSidOwner,
NULL,
NULL,
NULL,
&amp;pSD);
// Check GetLastError for GetSecurityInfo error condition.
if (dwRtnCode != ERROR_SUCCESS) {
DWORD dwErrorCode = 0;
dwErrorCode = GetLastError();
jstr = env-&gt;NewStringUTF(&quot;GetSecurityInfo error.\n&quot;);
return jstr;
}
// First call to LookupAccountSid to get the buffer sizes.
bRtnBool = LookupAccountSid(
NULL,           // local computer
pSidOwner,
AcctName,
(LPDWORD)&amp;dwAcctName,
DomainName,
(LPDWORD)&amp;dwDomainName,
&amp;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-&gt;NewStringUTF(&quot;GlobalAlloc error.\n&quot;);
return jstr;
}
DomainName = (LPTSTR)GlobalAlloc(
GMEM_FIXED,
dwDomainName);
// Check GetLastError for GlobalAlloc error condition.
if (DomainName == NULL) {
DWORD dwErrorCode = 0;
dwErrorCode = GetLastError();
jstr = env-&gt;NewStringUTF(&quot;GlobalAlloc error.\n&quot;);
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)&amp;dwAcctName,   // size of account name buffer
DomainName,             // domain name
(LPDWORD)&amp;dwDomainName, // size of domain name buffer
&amp;eUse);                 // SID type
// Check GetLastError for LookupAccountSid error condition.
if (bRtnBool == FALSE) {
DWORD dwErrorCode = 0;
dwErrorCode = GetLastError();
if (dwErrorCode == ERROR_NONE_MAPPED)
jstr = env-&gt;NewStringUTF(&quot;Account owner not found for specified SID.\n&quot;);
else
jstr = env-&gt;NewStringUTF(&quot;Error in LookupAccountSid.\n&quot;);
return jstr;
} else if (bRtnBool == TRUE)
{// Print the account name.
jstr = env-&gt;NewStringUTF(AcctName);
env-&gt;ReleaseStringUTFChars(path, str);
}
return jstr;
}

The same jni methods I actually used in the web project to get the file path in textfield and print owner which works perfectly fine.
enter image description here

答案1

得分: 0

请尝试执行一个简单的JNI HelloWorld程序,并查看是否有效。在我的情况下,传递字符串并返回名称的程序完全正常工作,而传递文件路径并返回所有者的相同方法类型则无效。

现在尝试在相同的JNI代码中添加不同的简单方法,与上面的方法一起查看是否有效。我曾经有一个复杂的方法返回文件的ACL,返回类型是字符串数组。我尝试执行一个不同的方法,返回星期几作为字符串数组,它有效。

现在,在执行上述JNI方法之后,更改您方法的逻辑,但不要更改返回类型和参数传递。

很奇怪,但它有效。

英文:

Anyone who's still facing this issue. Please try a simple JNI HelloWorld program execution and see if it works. In my case, a program passing string and returning name work perfectly fine, while the same method type passing file path and returning owner doesn't work.

JNIEXPORT jstring JNICALL Java_TestJNIString_sayHello(JNIEnv *env, jobject thisObj, jstring inJNIStr) {
const char *inCStr = (*env)-&gt;GetStringUTFChars(env, inJNIStr, NULL);
return (*env)-&gt;NewStringUTF(env, inCStr);
}

Now try to add different simple methods if you have, with above one in the same JNI code, and see it works. I had a complex method returning the ACL of a file with a return type string array. I tried executing a different method returning days of the week as string array and it works.

Now after executing the above JNI methods, make changes to the logic of your method but not return type and arguments passing.

It's weird but it worked.

huangapple
  • 本文由 发表于 2020年8月3日 14:09:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/63224515.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定