簡體   English   中英

使用 Java 在 Windows 中讀取內存映射文件

[英]Reading memory mapped file in Windows using Java

我使用此示例構建了一個程序,該程序正在創建包含字符串值“來自第一個進程的消息”的內存映射文件。

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>

#define BUF_SIZE 256
TCHAR szName[] = TEXT("Local\\MyFileMappingObject");
TCHAR szMsg[] = TEXT("Message from first process.");

int _tmain()
{
    HANDLE hMapFile;
    LPCTSTR pBuf;

    hMapFile = CreateFileMapping(
        INVALID_HANDLE_VALUE,    // use paging file
        NULL,                    // default security
        PAGE_READWRITE,          // read/write access
        0,                       // maximum object size (high-order DWORD)
        BUF_SIZE,                // maximum object size (low-order DWORD)
        szName);                 // name of mapping object

    if (hMapFile == NULL)
    {
        _tprintf(TEXT("Could not create file mapping object (%d).\n"),
            GetLastError());
        return 1;
    }
    pBuf = (LPTSTR)MapViewOfFile(hMapFile,   // handle to map object
        FILE_MAP_ALL_ACCESS, // read/write permission
        0,
        0,
        BUF_SIZE);

    if (pBuf == NULL)
    {
        _tprintf(TEXT("Could not map view of file (%d).\n"),
            GetLastError());

        CloseHandle(hMapFile);

        return 1;
    }


    CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
    _getch();

    UnmapViewOfFile(pBuf);

    CloseHandle(hMapFile);

    return 0;
}

我的 Java 應用程序讀取值時遇到問題。 String data = view.getString(0); 當上面的演示應用程序運行時,給我“java.lang.Error:無效的內存訪問”。

我知道函數成功是因為失敗(如果應用程序沒有運行)導致NullPointerException因為this.hnull 所以指針是正確的,但是在嘗試獲取值時我做錯了什么?

package ACC;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.win32.W32APIOptions;

public class ACCSharedMemory{
    private final MyKernel32 myKernel32;
    private HANDLE h;
    private Pointer view;
    
    public interface MyKernel32 extends Kernel32 {
        MyKernel32 INSTANCE = (MyKernel32)Native.load("kernel32", MyKernel32.class, W32APIOptions.DEFAULT_OPTIONS);
        HANDLE OpenFileMapping(int dwDesiredAccess, boolean bInheritHandle, String lpName);
    }
    
    public ACCSharedMemory() {
        myKernel32 = MyKernel32.INSTANCE;
    }

    public void test() {

        h = myKernel32.OpenFileMapping(983071, true, "Local\\MyFileMappingObject");
        view = h.getPointer();
        String data = view.getString(0);
    }
}

編輯。 完整的工作代碼如下。 謝謝丹尼爾和德雷克。

public class ACCSharedMemory{
    private final MyKernel32 myKernel32;
    private HANDLE h;
    private Pointer view;
    
    public interface MyKernel32 extends Kernel32 {
        MyKernel32 INSTANCE = (MyKernel32)Native.load("kernel32", MyKernel32.class, W32APIOptions.DEFAULT_OPTIONS);
        HANDLE OpenFileMapping(int dwDesiredAccess, boolean bInheritHandle, String lpName);
    }
    
    public ACCSharedMemory() {
        myKernel32 = MyKernel32.INSTANCE;
    }

    public void test() {
        h = myKernel32.OpenFileMapping(0x4, true, "Local\\MyFileMappingObject");
        view = Kernel32.INSTANCE.MapViewOfFile (h, 0x4, 0, 0, 256);
        System.out.println(view.getWideString(0));
    }
    
}

問題是您將返回的HANDLE視為指向數據的指針。 但它不是一個普通的指針; 它只對其他文件映射 API 函數有意義。

創建命名共享內存中的示例展示了如何在第二個進程中使用此返回的句柄。 請注意,處理檢索到的句柄值的本機代碼是將其傳遞給MapViewOfFile()指定要映射的起始偏移量和字節數,以及共享內存的權限。

該函數將返回指向共享內存的實際指針,然后您可以操作該指針(例如,檢索字符串)。

請注意,Windows 字符串采用 UTF-16,但使用Pointer.getString()將假定為 8 位 C 字符串。 您應該使用Pointer.getWideString() 為避免讀取超出內存范圍,您還應確保正在讀取的Pointer處的緩沖區足夠大以包含空終止符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM