Loading JNI Dll

ぐ巨炮叔叔 提交于 2019-12-11 04:55:13

问题


I have a file written as follows:

package JNI;

public class Natives {

    public static final int PAGE_READONLY = 0x02;
    public static final int PAGE_READWRITE = 0x04;
    public static final int PAGE_WRITECOPY = 0x08;
    public static final int FILE_MAP_COPY = 0x0001;
    public static final int FILE_MAP_WRITE = 0x0002;
    public static final int FILE_MAP_READ = 0x0004;

    public static native long createFileMapping(long hFile, int lpAttributes, int dwMaximumSizeHigh, int dwMaximumSizeLow, String lpName);

    public static native long openFileMapping(int dwDesiredAccess, boolean bInheritHandle, String lpName);

    public static native long mapViewOfFile(long hFileMap, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, int dwNumberOfBytesToMap);

    public static native long unmapViewOfFile(long hFileMap);

    public static native long closeHandle(long hFile);
}

Then I generate the jni file using javah:

extern "C" JNIEXPORT jlong JNICALL Java_JNI_Natives_createFileMapping(JNIEnv *env, jclass, jlong hFile, jint lpProtect, jint dwMaximumSizeHigh, jint dwMaximumSizeLow, jstring lpName)
{
    HANDLE hFileMap = nullptr;
    LPCSTR Name = env->GetStringUTFChars(lpName, nullptr);

    if ((hFileMap = CreateFileMapping(hFile == -1 ? INVALID_HANDLE_VALUE : reinterpret_cast<HANDLE>(hFile), nullptr, lpProtect, dwMaximumSizeHigh, dwMaximumSizeLow, Name)) != nullptr)
    {
        if (errno ==  ERROR_ALREADY_EXISTS)
        {
            CloseHandle(hFileMap);
        }
    }

    env->ReleaseStringUTFChars(lpName, Name);
    return reinterpret_cast<jlong>(hFileMap);
}

extern "C" JNIEXPORT jlong JNICALL Java_JNI_Natives_openFileMapping(JNIEnv *env, jclass, jint dwDesiredAccess, jboolean bInheritHandle, jstring lpName)
{
    LPCSTR Name = env->GetStringUTFChars(lpName, nullptr);
    HANDLE hFileMap = OpenFileMapping(dwDesiredAccess, static_cast<bool>(bInheritHandle), Name);
    env->ReleaseStringUTFChars(lpName, Name);
    return reinterpret_cast<jlong>(hFileMap);
}

extern "C" JNIEXPORT jlong JNICALL Java_JNI_Natives_mapViewOfFile(JNIEnv *, jclass, jlong hFileMap, jint dwDesiredAccess, jint dwFileOffsetHigh, jint dwFileOffsetLow, jint dwNumberOfBytesToMap)
{
    void* pData = MapViewOfFile(reinterpret_cast<HANDLE>(hFileMap), dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap);
    return reinterpret_cast<jlong>(pData);
}

extern "C" JNIEXPORT jlong JNICALL Java_JNI_Natives_unmapViewOfFile(JNIEnv *, jclass, jlong hFileMap)
{
    return reinterpret_cast<jboolean>(static_cast<uint8_t>(UnmapViewOfFile(reinterpret_cast<void*>(hFileMap))));
}

extern "C" JNIEXPORT jlong JNICALL Java_JNI_Natives_closeHandle(JNIEnv *, jclass, jlong hFile)
{
    return reinterpret_cast<jboolean>(static_cast<uint8_t>(CloseHandle(reinterpret_cast<HANDLE>(hFile))));
}

But as soon as the DLL loads and I call a function like so:

long Handle = Natives.createFileMapping(-1, Natives.FILE_MAP_READ | Natives.FILE_MAP_WRITE, 500, 0, "NativeDLL"); debug(Handle);

it prints:

run:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000061288f69, pid=4692, tid=844
#
# JRE version: 7.0_21-b11
# Java VM: Java HotSpot(TM) 64-Bit Server VM (23.21-b01 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# V  [jvm.dll+0x38f69]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Users\Brandon\Documents\NetBeansProjects\Smart\hs_err_pid4692.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
#
Java Result: 1

Any ideas what I did wrong?


回答1:


I suggest that you code and build your JNI DLL with Unicode support, and use GetStringChars to create UTF-16 strings to pass to CreateFileMapping. No version of CreateFileMapping takes the UTF-8 strings that are returned by GetStringUTFChars. If you must use the ANSI version then do a proper conversion from Unicode to ANSI strings before calling CreateFileMapping.

IMO, GetStringUTFChars should be named GetStringUTF8Chars.

Don't forget to pair GetStringChars with ReleaseStringChars.




回答2:


It may be a permissions issue.

You may consider using Java Native Access/JNA which has a more tried & robust implementation of the native Platform APIs than you could implement alone (depending on experience of course). It is used by Netbeans IDE among others.

See specifically the com.sun.jna.platform.win32 Kernel32 Interface which contains these methods.



来源:https://stackoverflow.com/questions/16484770/loading-jni-dll

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!