IllegalMonitorStateException when creating an object - java

I'm getting IllegalMonitorStateException when I'm trying to create an instance of an object. The code looks like the following:
public int signIn(parameters...)
{
...check some stuff...
new Thread(... just a simple log here...).start();//IllegalMonitorStateException
return result;
}
MORE INFO:
The actual application consists of 2 programs (C++ and java) interacting via JNI). The scenario in which I'm getting exception is as follows.
The c++ program asks java to connect to a server. (this is a non blocking operation)
Java program informs c++ about connection success. (in a new thread so that java can continue doing other tasks)
When receiving connection success, c++ program asks java to login
Exception occurs.
I should note that this exception only happens in this special scenario and if I call login sometime after connection success everything works fine.
What I've tried:
In the beginning informing connection success was not in a new thread, but creating the thread did not solve the problem.
The java login code had some synchronization stuff but removing them and replacing it with a simple log still produces the problem.
EDIT:
Here's the stacktrace:
Phoenix.client.ClientAPI.NativeInterface.NativeAPIEventListener.onConnectingFinished(Native
Method)
Phoenix.client.ClientAPI.NativeInterface.NativeAPIEventListener.access$000(NativeAPIEventListener.java:12)
Phoenix.client.ClientAPI.NativeInterface.NativeAPIEventListener$1.run(NativeAPIEventListener.java:30)
java.lang.Thread.run(Unknown Source)

I created a new thread in C++ code when java code called back into it This broke the jthread:java -> c++ -> java chain into jthread:java -> c++ and cthread:c++ -> java. This solved the problem I was facing. However I ran into a different problem which lead me into reading a bit of JNI documentation. Quoting JNI doc:
The JNI interface pointer (JNIEnv) is valid only in the current
thread. Should another thread need to access the Java VM, it must
first call AttachCurrentThread() to attach itself to the VM and obtain
a JNI interface pointer. Once attached to the VM, a native thread
works just like an ordinary Java thread running inside a native
method. The native thread remains attached to the VM until it calls
DetachCurrentThread() to detach itself.
So I guess I should've called AttachCurrentThread before calling back into java. However this does not exactly fit in the above description since the thread was not a native thread (it was a thread originally created in java code, could I call DetachCurrentThread afterwards?). I did not test this solution since I had to create a new thread other reasons too. But if I get a chance to try this out I'll confirm.

Related

Java ExecutorService threads with functions that don't support threading

I am trying to leverage multi-threading for quite a heavy image processing program. The multi-threading is mostly working great and decreasing my runtime x4. However, some external libraries that I am using are not very stable when being executed by multiple thread and I occasionally get errors which reflect that (for example, an empty image error when in fact no images are empty etc.)
I have identified two such functions that belong to an external library (opencv) and I would like to isolate those if possible, so that when a thread hit that function, it always waits for the previous thread to finish - this way the problematic functions will never be executed more than once at a given time.
Can this be achieved in Java? How?
Thanks
UPDATE : synchronized Java function does not work. Occasionally (it is hard to reproduce which is why it is so frustrating) I would see an opencv error coming from a function that works fine 99.9% of the runs.
An example of an error I just recently got, and related to the opencv fillPolyfunction:
ERROR main.java.com.ibm.staple.Staple - cv Exception: OpenCV(4.0.0) C:\build\master_winpack-bindings-win64-vc14-static\opencv\modules\imgproc\src\drawing.cpp :2403 error: (-215:Assertion failed) p.checkVector(2, CV_32S) >= 0 in function ‘cv::fillPoly’
You can easily acheive this using Synchronization in Java. Synchronization will make the method accessible to only one thread at a time. You can find lots of article in google about Synchronization.
Ex :
synchronized void yourMethodname(int x){//synchronized method
// Your code block inside.
}

JNI call fails in driver callback

I am developing an application that interacts with a hardware device. Using the dll file provided with the hardware's official application, I initialize the device and register some function as a callback to be called upon some user interaction. In this callback function, I want to call a Java function to transfer data. However, the whole application exits without any error log just at this call in the callback:
jclass cls = env->FindClass("java/lang/String");
The same call works if it is executed in the function that is called directly by Java.
What is the reason of this behaviour? How does it make difference to call JNI from device driver calls? Any help is appreciated.
EDIT: I tried Vernee's suggestion and tried to attach the driver thread to JVM, however the behaviour didn't change. Moreover, I lost the printf outputs, which are -unfortunately- my only option to debug JNI side. They work before the attach operation, but stop working thereafter.
If you are developing on Windows, I strongly suggest you that you use visual studio to debug the C code. You can start your java program and place a breakpoint on System.load, when the Java program stops at this point, go to Visual studio and from tools > attach process, this way you can stop at breakpoints placed in the C code. After that just resume the java code. Calling a java method from C thread requires some preperation:
1- Cache JVM object
JavaVM * javaVm;
(*jenv)->GetJavaVM(jenv, &javaVm);
2- Cache the Class object of the Class that contains your java callback method.
clazz = (*jenv)->NewGlobalRef(jenv, (*jenv)->FindClass(jenv, "com/something/somepackage/SomeClass"));
3- If you are calling instance method, you will also need to cahce the instance being called
callback = (*jenv)->NewGlobalRef(jenv, callbackInstance);
4- Attach native thread to virtual machine (When you need to make the call to java method)
JNIEnv * jenv;
int errorCode = (*j_javaVm)->AttachCurrentThread(j_javaVm, (void**) &jenv, NULL);
5- Get the method ID you need to call (When you need to make the call to java method)
jmethodID methodID = (*jenv)->GetMethodID(jenv, cachedhandlerClass, "methodNameHere", "methodSignetureHere");
6- Make the method call
(*jenv)->CallVoidMethod(jenv, cachedCallbackInstance, methodID, param1, param2,....);
7- deattach the native thread
(*j_javaVm)->DetachCurrentThread(j_javaVm);
Steps 1,2 and 3 require a java environment and they can be done in JNI_OnLoad method or in the implementation of a native Java method.

.NET GC stuck on JNI call from finalizer()

I have a .NET application that is using JNI to call Java code. On the .NET finalizer we call a JNI call to clean the connected resource on Java. But from time to time this JNI gets stuck.
This as expected stuck the all .NET process and never releases.
Bellow you can see the thread dump we got from .NET:
NET Call Stack
Function
.JNIEnv_.NewByteArray(JNIEnv_*, Int32)
Bridge.NetToJava.JVMBridge.ExecutePBSCommand(Byte[], Int32, Byte[])
Bridge.Core.Internal.Pbs.Commands.PbsDispatcher.Execute(Bridge.Core.Internal.Pbs.PbsOutputStream, Bridge.Core.Internal.DispatcherObjectProxy)
Bridge.Core.Internal.Pbs.Commands.PbsCommandsBundle.ExecuteGenericDestructCommand(Byte, Int64, Boolean)
Bridge.Core.Internal.DispatcherObjectProxy.Dispose(Boolean)
Bridge.Core.Internal.Transaction.Dispose(Boolean)
Bridge.Core.Internal.DispatcherObjectProxy.Finalize()
Full Call Stack
Function
ntdll!KiFastSystemCallRet
ntdll!NtWaitForSingleObject+c
kernel32!WaitForSingleObjectEx+ac
kernel32!WaitForSingleObject+12
jvm!JVM_FindSignal+5cc49
jvm!JVM_FindSignal+4d0be
jvm!JVM_FindSignal+4d5fa
jvm!JVM_FindSignal+beb8e
jvm+115b
jvm!JNI_GetCreatedJavaVMs+1d26
Bridge_NetToJava+1220
clr!MethodTable::SetObjCreateDelegate+bd
clr!MethodTable::CallFinalizer+ca
clr!SVR::CallFinalizer+a7
clr!WKS::GCHeap::TraceGCSegments+239
clr!WKS::GCHeap::TraceGCSegments+415
clr!WKS::GCHeap::FinalizerThreadWorker+cd
clr!Thread::DoExtraWorkForFinalizer+114
clr!Thread::ShouldChangeAbortToUnload+101
clr!Thread::ShouldChangeAbortToUnload+399
clr!ManagedThreadBase_NoADTransition+35
clr!ManagedThreadBase::FinalizerBase+f
clr!WKS::GCHeap::FinalizerThreadStart+10c
clr!Thread::intermediateThreadProc+4b
kernel32!BaseThreadStart+34
I have no idea whether .NET finalizers are equally bad idea to Java finalizers, but using a potentially (dead)locking code (i see Win32 condition call at the very bottom) from anything like finalizer (regardless of the platform) is definitely a bad idea. You need to clean your native code of any potential locking, or have an emergency brake timeout at the level of .NET
As I didn't find a question I won't post a formal answer here but rather tell a story about something similar I underwent sometimes:
We created C ojects via JNI, that were backed by java object, and we decided to clean the C objects within the finalize method. However, we envisioned deadlocks, as the finalize is called from a non-application thread, the garbage-collector. As the entire wolrd is stopped while collecting the garbage, whenever the finalizer meets a lock it's immediately a dead lock. Thus we decided to use a java mechnism called phantom references. It's possible to bind a number to each of these 'references' (the C pointer) and then the VM removes an referenced object it puts such an reference into a queue. And one can pull this data whenever appropriate and remove the C object.
I think at least your problem is the same.

Introducing delay in a java program

I am calling a .exe file from my java code using :
Runtime r=Runtime.getRuntime();
Process p=null;
p=r.exec("ABCD.exe");
I want the program to wait till the exe completes its job .(This is actually server side code...control passes to Client side after this).The problem now is that UI on client side is populated before the .exe on server side can form the required components.Hence UI formed does not have the correct files.
I have tried the normal p.waitfor() thing but it doesn't seem to work.
Any suggestions?
The short answer is that you want to call Process.waitFor() in your main thread, as you allude to.
However, dealing with Processes is not exactly fire-and-forget, because, as referenced by the class javadocs, you likely need to be reading the process' output. If you don't do this (which in this case will require a separate thread) then in many instances you'll have an effective deadlock - your Java app is waiting for the process to finish, but the process is trying to write output to a full buffer and thus waiting for the Java app to read its output.
If you gave more information about how "it didn't work", that would help with the diagnosis too.
Edit: on a completely separate point, there's no purpose in initialising p to null and then immediately reassigning it. Your second line would be clearer and less confusing as Process p = r.exec("ABCD.exe");.

JACOB doesn't release the objects properly

I have an eclipse plugin, which connects to a COM component using Jacob. But after I close the plugin entirely, the .exe file stays hanging in Windows processes.
I use ComThread.InitMTA(true) for initialization and make sure that SafeRelease() is called for every COM object I created before closing the app and I call ComThread.Release() at the very end.
Do I leave something undone?
Some further suggestions:
Move the call to ComThread.Release() into a finally block, otherwise the thread will remain attached if an exception is thrown.
Check that you are calling ComThread.InitMTA and ComThread.Release in every thread that uses a COM object. If you forget to do this in a worker thread then that thread will be attached automatically and never detached.
Avoid InitSTA and stick to InitMTA. Even when there is only one thread using COM, I have found InitSTA to be flaky. I don't know how JACOB's internal marshalling mechanism works but I have ended up with "ghost" objects that appear to be valid but do nothing when their methods are invoked.
Fortunately I have never yet needed to modify any code in the JACOB library.
I ran into this issue myself. After messing with initMTA,etc. I found a simple fix - when you start Java add the following to your command line:
-Dcom.jacob.autogc=true
This will cause the ROT class to use a WeakHashMap instead of a HashMap and that solves the problem.
You can also use -Dcom.jacob.debug=true to see lots of informative debug spew and watch the size of the ROT map.
Had the same problem with TD2JIRA converter. Eventually had to patch one of the Jacob files to release the objects. After that all went smooth.
The code in my client logout() method now looks like this:
try {
Class rot = ROT.class;
Method clear = rot.getDeclaredMethod("clearObjects", new Class[]{});
clear.setAccessible(true);
clear.invoke(null, new Object[]{});
} catch( Exception ex ) {
ex.printStackTrace();
}
The ROT class wasn't accessible initially, AFAIR.
Update
The correct way to release resources in Jacob is to call
ComThread.InitSTA(); // or ComThread.InitMTA()
...
ComThread.Release();
Bad thing though is that sometimes it doesn't help. Despite Jacob calls native method release(), the memory (not even Java memory, but JVM process memory) grows uncontrollably.

Categories