Ошибка JNI Исключение в потоке «main» java .lang.UnsatisfiedLinkError: (Ljava / lang / String;) Ljava / lang / String; - PullRequest
0 голосов
/ 03 августа 2020

У меня есть собственный метод, который отображает владельца файла для заданного пути.

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

Код, показывающий эту ошибку при запуске

Исключение в потоке «main» java .lang.UnsatisfiedLinkError: ACL.displayFileOwner (Ljava / lang / String;) Ljava / lang / String; в ACL.displayFileOwner (собственный метод) в 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;
}

Те же методы jni, которые я фактически используется в веб-проекте для получения пути к файлу в текстовом поле и владельца печати, который отлично работает. введите описание изображения здесь

1 Ответ

0 голосов
/ 05 августа 2020

Всем, кто все еще сталкивается с этой проблемой. Попробуйте выполнить простую программу JNI HelloWorld и посмотрите, работает ли она. В моем случае программа, передающая строку и возвращающее имя, работает отлично, в то время как тот же тип метода, передающий путь к файлу и возвращающий владелец, не работает.

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, и посмотрите, как он работает. У меня был сложный метод, возвращающий ACL файла с массивом строк возвращаемого типа. Я попытался выполнить другой метод, возвращающий дни недели в виде массива строк, и он работает.

Теперь, после выполнения вышеуказанных методов JNI, внесите изменения в logi c вашего метода, но не возвращайте тип и передаваемые аргументы .

Странно, но сработало.

...