我制作了一个调用JNI的Java程序,它在JNI中创建了一个“JNICallback”线程,并在其中执行env-attachCurrentThreadAsDaemon()
我做标准的事情,比如
synchronized -> wait, synchronized -> notifyAll
,使用
static final Object
如果我在Eclipse下运行它,一切正常。
但如果我将其导出为“可运行jar文件”并在同一JVM下运行,我会看到我的JNI程序调用
monitorEnter, notifyAll, monitorExit
没有错误,但是Java没有被通知。
在调试器中,我看到JNI和Java中使用的同一对象的ObjectId不同,这对我来说是可疑的(下面的代码中是names OnConnectionEvent)
我甚至将通知代码从JNI移动到Java,并使用来自JNI的静态void方法调用,执行同步->notifyAll在Java中,但这只显示等待线程在不同的ObjectId上等待,所以我猜这就是原因。
...
static final Object onConnectEvent = new Object();
...
Thread dogServerConnect,...;
...
public MainClass(){
dogServerConnect = runDog(new ServerConnectionWatchDog(), "onServerConnect");
someJNIstuffPlusNewThreadsCreation();
...
static void onJNICallbackEvent(int type) {
switch (type) {
case 1 -> {
synchronized(onConnectEvent) {
onConnectEvent.notifyAll();
^^^^^ got to this line from JNI, just fine
}
...
class ServerConnectionWatchDog implements Runnable {
@Override
public void run() {
while(true)
synchronized(onConnectEvent) {
try {
onConnectEvent.wait();
for (var l : listeners) {
^^^^^^^^^^^^^^^^^^^^^^^^^ never come to this line
...
同样,这在Eclipse下确实工作得很好,但由于某些原因,作为单独的jar文件失败。
我的意思是,对于正在等待的线程,Eclipse向我显示“正在等待:对象(id=48)”,对于“notifyAll”执行之前的本机线程,Eclipse向我显示“拥有:对象(id=50)”。可能这是因为我手动暂停等待的线程,以查看对象id(然后再次运行它,这不是原因)
我会错过什么?