如何修复java上dll calback调用的无效内存访问?

时间:2014-07-18 11:07:18

标签: java c++ dll jna

我有一个单独的线程,它在一个while / call / sleep循环中从DLL调用一个方法,在它上面调用我的java应用程序的映射回调。 cabinet.ProcessCallbacks.apply()的第一次调用成功,但所有后续调用都以java.lang.Error: Invalid Memory Access失败,这非常奇怪。你知道为什么会发生这种情况以及如何解决它吗?

private void registerCallbacksCycle(final int rate) {
    Thread buttonsCycle = new Thread() {
    @Override
    public void run() {
        while(true) {
            try {
                System.out.println("Refreshing Callbacks ...");
                try {
                    System.out.println("       ");
                    byte b = cabinet.ProcessCallbacks.apply();
                    System.out.println("result " + b);
                } catch(Error e) {
                    e.printStackTrace();
                }
            System.out.println("Refreshing Callbacks END ...");
            sleep(rate);
            System.out.println("Refreshing Callbacks AFTER SLEEP ...");
            } catch (Exception e1) {
                System.out.println("Refreshing Callbacks EXCEPTION ");
                e1.printStackTrace();
            }
        }
    }

    };
    buttonsCycle.start();

    System.out.println("Callback Cycles started successfully ... ");
}

[更新] Java映射到DLL:

public class OGAPI_CabinetButtons_Interface_v1 extends Structure {
    /** C type : Initialize_callback* */
    public OGAPI_CabinetButtons_Interface_v1.Initialize_callback Initialize;
    /** C type : ProcessCallbacks_callback* */
    public OGAPI_CabinetButtons_Interface_v1.ProcessCallbacks_callback ProcessCallbacks;
    /** C type : Shutdown_callback* */
    public OGAPI_CabinetButtons_Interface_v1.Shutdown_callback Shutdown;
    /** C type : SetButtonCallback_callback* */
    public OGAPI_CabinetButtons_Interface_v1.SetButtonCallback_callback SetButtonCallback;
    /** C type : SetLights_callback* */
    public OGAPI_CabinetButtons_Interface_v1.SetLights_callback SetLights;
    public interface Initialize_callback extends Callback {
        byte apply();
    };
    public interface ProcessCallbacks_callback extends Callback {
        byte apply();
    };
    public interface Shutdown_callback extends Callback {
        void apply();
    };
    public interface SetButtonCallback_callback extends Callback {
        void apply(ButtonCallback cb, Pointer userData);
    };
    public interface SetLights_callback extends Callback {
        void apply(int lights);
    };
    public OGAPI_CabinetButtons_Interface_v1() {
        super();
    }
    protected List<? > getFieldOrder() {
        return Arrays.asList("Initialize", "ProcessCallbacks", "Shutdown", "SetButtonCallback", "SetLights");
    }
    /**
     * @param Initialize C type : Initialize_callback*<br>
     * @param ProcessCallbacks C type : ProcessCallbacks_callback*<br>
     * @param Shutdown C type : Shutdown_callback*<br>
     * @param SetButtonCallback C type : SetButtonCallback_callback*<br>
     * @param SetLights C type : SetLights_callback*
     */
    public OGAPI_CabinetButtons_Interface_v1(OGAPI_CabinetButtons_Interface_v1.Initialize_callback Initialize, OGAPI_CabinetButtons_Interface_v1.ProcessCallbacks_callback ProcessCallbacks, OGAPI_CabinetButtons_Interface_v1.Shutdown_callback Shutdown, OGAPI_CabinetButtons_Interface_v1.SetButtonCallback_callback SetButtonCallback, OGAPI_CabinetButtons_Interface_v1.SetLights_callback SetLights) {
        super();
        this.Initialize = Initialize;
        this.ProcessCallbacks = ProcessCallbacks;
        this.Shutdown = Shutdown;
        this.SetButtonCallback = SetButtonCallback;
        this.SetLights = SetLights;
    }
    public OGAPI_CabinetButtons_Interface_v1(Pointer peer) {
        super(peer);
        read();
    }
    public static class ByReference extends OGAPI_CabinetButtons_Interface_v1 implements Structure.ByReference {

    };
    public static class ByValue extends OGAPI_CabinetButtons_Interface_v1 implements Structure.ByValue {

    };
}

似乎只有当我从不同的线程调用DLL时才会发生这种情况。事件Native.synchronizedLibrary无济于事。

[更新2 ]

public class IKernel {

    private static final Logger logger = LoggerFactory.getLogger(IKernel.class);

    private static final String OGAPI_DLL = "ogapiDLL_Release";
    private static final String ADMIN_V = "admin_v1";
    private static final String LEGION_CORE_V = "legion_core_v1";
    private static final String DEBUG_V = "debug_v1";
    private static final String CABINET_V = "cabinet_buttons_v1";

    private static Object HANDLE = new Object();
    public static String CONTENT_ID = "999406";
    public static Integer LOG_LEVEL = 3;
    public static Integer CALLBACK_REFRESH_RATE = 2000;

    protected static IKernel kernel;

    private OGAPI_Admin_Interface_v1 admin;
    private OGAPI_LegionCore_Interface_v1 core;
    private OGAPI_CabinetButtons_Interface_v1 cabinet;

    public static IKernel instance() {
        if (kernel == null) {
            synchronized (HANDLE) {
                kernel = new IKernel(CONTENT_ID, LOG_LEVEL, CALLBACK_REFRESH_RATE);
            }
        }

        return kernel;
    }

    protected IKernel(String contentId, int logLevel, int rate) {

        initialize(contentId, logLevel);

        registerCallbacksCycle();
    }

    private void initialize(String contentId, int logLevel) {
        logger.info("OGAPI Initialization started ...");

        OGAPILibrary ogapi = (OGAPILibrary) Native
            .synchronizedLibrary((OGAPILibrary) Native.loadLibrary(
                    OGAPI_DLL, OGAPILibrary.class));
        admin = ogapi.RequestAdminInterface(ADMIN_V);

        OGAPI_Admin_Interface_v1.RequestInterface_callback request = admin.RequestInterface;

        Pointer coreIntPointer = request.apply(LEGION_CORE_V);
        core = new OGAPI_LegionCore_Interface_v1(coreIntPointer);

        Pointer debugIntPointer = request.apply(DEBUG_V);
        OGAPI_Debug_Interface_v1 debug = new OGAPI_Debug_Interface_v1(debugIntPointer);

        if (contentId != null) {
            debug.SetContentID.apply(contentId);
        }

        admin.SetLoggingCallback.apply(new LoggingCallback() {
            public void apply(Pointer userData, String msg, int level) {
                logger.info("Remote Logger: " + msg);
            }
        }, null);
        admin.SetLoggingLevel.apply(logLevel);

        Pointer cabinetIntPointer = request.apply(CABINET_V);
        cabinet = new OGAPI_CabinetButtons_Interface_v1(cabinetIntPointer);

        boolean success = admin.Initialize.apply() == 1
            && cabinet.Initialize.apply() == 1;
        if (!success) {
            throw new RuntimeException("ikernel initialization failed");
        }
        logger.info("OGAPI Initialization completed successfully ...");
    }

    private void registerCallbacksCycle() {
        Thread buttonsCycle = new Thread() {
            @Override
            public void run() {
                while (true) {
                    try {
                        logger.info("Refreshing Callbacks ...");
                        try {
                            logger.info("       ");
                            byte b = cabinet.ProcessCallbacks.apply();
                            logger.info("result " + b);
                        } catch (Error e) {
                            e.printStackTrace();
                        }
                        logger.info("Refreshing Callbacks END ...");
                        sleep(CALLBACK_REFRESH_RATE);
                        logger.info("Refreshing Callbacks AFTER SLEEP ...");
                    } catch (Exception e1) {
                        logger.info("Refreshing Callbacks EXCEPTION ");
                        e1.printStackTrace();
                    }
                }
            }

        };
        buttonsCycle.start();

        logger.info("Callback Cycles started successfully ... ");
    }
}

CabinetInterface方法的标题:

typedef void (__cdecl *ButtonCallback )( void* userData, int buttonIndex, int pressed );

typedef struct tag_OGAPI_CabinetButtons_Interface_v1 {

    bool (__cdecl *Initialize)();
    bool (__cdecl *ProcessCallbacks)();
    void (__cdecl *Shutdown)();
    void (__cdecl *SetButtonCallback)( ButtonCallback cb, void* userData );
    void (__cdecl *SetLights)( unsigned int lights );

} OGAPI_CabinetButtons_Interface_v1;

0 个答案:

没有答案