我有一个单独的线程,它在一个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;