通过JNI

如何解决通过JNI

我有一个Java类,调用本地方法ACLInfo(String path),该本地方法应返回HashMap以在Java中使用。这是Java代码。

import java.util.*;

public class test
{
  native Map<String,String[]> ACLInfo(String s);
  
   static
   {
      System.loadLibrary("test");
   }
  
   static public void main(String args[])
   {
   
      test obj = new test();
      Map<String,String[]> map = obj.ACLInfo("C:/Windows/Boot/Resources/bootres.dll");

      for (Map.Entry<String,String[]> entry : map.entrySet())
      {
          String name = entry.getKey();
          System.out.println("Name:"+name);
          System.out.println("Properties are:");
          for(String text : entry.getValue())
          {
              if(text.equals("Full Control")){
                 System.out.println(text);
                 continue;
             }
              if(text.equals("Read"))
                 System.out.println(text);
             if(text.equals("Write"))
                 System.out.println(text);
             if(text.equals("Execute"))
                 System.out.println(text);
          }
          
      }
   }
}

本机代码是

#include <iostream>
#include <jni.h>
#include <string.h>
#include <windows.h>
#include <tchar.h>
#include <Lmcons.h>
#include "test.h"
#include "accctrl.h"
#include "aclapi.h"

using namespace std;

JNIEXPORT jobject JNICALL Java_test_ACLInfo(JNIEnv *env,jobject jobj,jstring s)
{
    jobjectArray ret;
    jstring jstr;
    PSID pSidOwner = NULL;
    BOOL bRtnBool = TRUE;
    DWORD dwRtnCode = 0;
    SID_NAME_USE eUse = SidTypeUnknown;
    HANDLE hFile;
    PSECURITY_DESCRIPTOR pSD = NULL;
    PACL pOldDACL = NULL;
    int i,aceNum;
    const char* test;
    std::string name,reslt;

    const char* nativeString = env->GetStringUTFChars(s,0);
    LPCSTR file = nativeString;
    // Get the handle of the file object.
    hFile = CreateFile(
                  file,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);


    // Get the SID of the file.
    dwRtnCode = GetSecurityInfo(
                  hFile,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,&pSidOwner,&pOldDACL,&pSD);

    PACL pAcl = pOldDACL;
    aceNum = pOldDACL->AceCount;

    ret = (jobjectArray)env->NewObjectArray(3,env->FindClass("java/lang/String"),env->NewStringUTF(""));

    jclass mapClass = env->FindClass("java/util/HashMap");      //HashMap class in java library
    if(mapClass == NULL)
    {
        return NULL;
    }
    jsize map_len = aceNum;
    jmethodID init = env->GetMethodID(mapClass,"<init>","(I)V");  //constructor of HashMap class
    jobject hashMap = env->NewObject(mapClass,init,map_len);      //creating a new object for that class
    jmethodID put = env->GetMethodID(mapClass,"put","(Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String;");

    for (i = 0; i < aceNum; i++)
    {
    PACCESS_ALLOWED_ACE AceItem;
    ACE_HEADER *aceAddr = NULL;
    if (GetAce(pOldDACL,i,(LPVOID*)&AceItem) && GetAce(pOldDACL,(LPVOID*)&aceAddr))
        {
        LPTSTR AccountBuff = NULL,DomainBuff = NULL;
        DWORD AccountBufflength = 1,DomainBufflength = 1;
        PSID_NAME_USE peUse = new SID_NAME_USE;
        PSID Sid = &AceItem->SidStart;
        LookupAccountSid(NULL,Sid,AccountBuff,(LPDWORD)&AccountBufflength,DomainBuff,(LPDWORD)&DomainBufflength,peUse);

        AccountBuff = (LPSTR)malloc(AccountBufflength * sizeof(LPSTR));
        DomainBuff = (LPSTR)malloc(DomainBufflength * sizeof(LPSTR));

        LookupAccountSid(NULL,&AccountBufflength,&DomainBufflength,peUse);

        std::string acc=AccountBuff;
        std::string dom=DomainBuff;
        name = acc+"\\"+dom;

        ACCESS_MASK Mask = AceItem->Mask;
        if (((Mask & GENERIC_ALL) == GENERIC_ALL) || ((Mask & FILE_ALL_ACCESS) == FILE_ALL_ACCESS)){
         reslt="Full Control";
         test = reslt.c_str();
         env->SetObjectArrayElement(ret,env->NewStringUTF(test));
         env->CallObjectMethod(hashMap,put,env->NewStringUTF(name.c_str()),ret);
         continue;
        }
         int j=0;
        if (((Mask & GENERIC_READ) == GENERIC_READ) || ((Mask & FILE_GENERIC_READ) == FILE_GENERIC_READ))
            {
                reslt="Read";
                test = reslt.c_str();
                env->SetObjectArrayElement(ret,j++,env->NewStringUTF(test));
            }
        if (((Mask & GENERIC_WRITE) == GENERIC_WRITE) || ((Mask & FILE_GENERIC_WRITE) == FILE_GENERIC_WRITE))
            {
                reslt="Write";
                test = reslt.c_str();
                env->SetObjectArrayElement(ret,env->NewStringUTF(test));
            }
        if (((Mask & GENERIC_EXECUTE) == GENERIC_EXECUTE) || ((Mask & FILE_GENERIC_EXECUTE) == FILE_GENERIC_EXECUTE))
            {
                reslt="Execute";
                test = reslt.c_str();
                env->SetObjectArrayElement(ret,env->NewStringUTF(test));
            }
        env->CallObjectMethod(hashMap,ret);
        }
    }
    return hashMap;
}

在运行该Java类时,它显示:Java运行时环境检测到致命错误:EXCEPTION_ACCESS_VIOLATION(0xc0000005)位于pc = 0x000000006d6cd4ed,pid = 19504,tid = 0x0000000000003da0

有什么问题? 我已经利用了这个stackoverflow帖子来创建哈希图How to create HashMap<String,String> through JNI then parse to java

解决方法

我已经重写了您的代码,以摆脱最严重的错误:

  • 您为HashMap#put签名是错误的。
  • 您必须为放入哈希图中的每个元素创建一个string[]。如果您重复使用同一对象,则将获得同一string[]的N个副本。
  • 您不能预先创建大小为3的数组,而只能填写一些插槽。最好在C ++领域中使用临时向量并在以后创建正确的数组大小。
  • 您需要使用PushLocalFrame和PopLocalFrame来确保您不会超出本地参考预算。

我还删除了很多非JVM的组件。请尽量减少示例代码的内容。

JNIEXPORT jobject JNICALL Java_test_ACLInfo(JNIEnv *env,jobject jobj,jstring s)
{

    // removed stuff
    jclass mapClass = env->FindClass("java/util/HashMap");      //HashMap class in java library
    jclass stringClass = env->FindClass("java/lang/String");
    if(mapClass == NULL)
    {
        return NULL;
    }
    jsize map_len = aceNum;
    jmethodID init = env->GetMethodID(mapClass,"<init>","(I)V");  //constructor of HashMap class
    jobject hashMap = env->NewObject(mapClass,init,map_len);      //creating a new object for that class
    jmethodID put = env->GetMethodID(mapClass,"put","(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");

    for (i = 0; i < aceNum; i++) {
        // removed stuff

        PACCESS_ALLOWED_ACE AceItem;
        ACE_HEADER *aceAddr = NULL;
        if (GetAce(pOldDACL,i,(LPVOID*)&AceItem) && GetAce(pOldDACL,(LPVOID*)&aceAddr)) {
            // removed more stuff
            std::string name = std::string(AccountBuff)+"\\"+std::string(DomainBuff);
            std::vector<std::string> perms;

            ACCESS_MASK Mask = AceItem->Mask;
            if (((Mask & GENERIC_ALL) == GENERIC_ALL) || ((Mask & FILE_ALL_ACCESS) == FILE_ALL_ACCESS)) {
                perms.emplace_back("Full Control");
            } else {
                if (((Mask & GENERIC_READ) == GENERIC_READ) || ((Mask & FILE_GENERIC_READ) == FILE_GENERIC_READ)) {
                    perms.emplace_back("Read");
                }
                if (((Mask & GENERIC_WRITE) == GENERIC_WRITE) || ((Mask & FILE_GENERIC_WRITE) == FILE_GENERIC_WRITE)) {
                    perms.emplace_back("Write");
                }
                if (((Mask & GENERIC_EXECUTE) == GENERIC_EXECUTE) || ((Mask & FILE_GENERIC_EXECUTE) == FILE_GENERIC_EXECUTE)) {
                    perms.emplace_back("Execute");
                }
            }

            env->PushLocalFrame(10);
            jobject ret = env->NewObjectArray(perms.size(),stringClass,nullptr);
            for (int i = 0; i < perms.size(); i++) {
                env->SetObjectArrayElement(ret,env->NewStringUTF(perms[i].c_str()));
            }
            env->CallObjectMethod(hashMap,put,env->NewStringUTF(name.c_str()),ret);
            env->PopLocalFrame(nullptr);
        }
    }
    return hashMap;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-