如何解决通过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 举报,一经查实,本站将立刻删除。