1

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)

atoMerz
  • 7,534
  • 16
  • 61
  • 101
  • 2
    You gave a lot of irrelevant information, but failed to provide the essentials: exception stacktrace and the exact code lines pointed out by the stacktrace. – Marko Topolnik Sep 06 '14 at 09:14
  • I copied the stack trace, but it does not contain valid info. That's because a java thread has gone into c++ and thus lost its context. So when c++ calls back in java again the call stack doesn't contain valid info. What you're seeing the stack trace is the trace before calling in c++. – atoMerz Sep 06 '14 at 09:28
  • 1
    But without that you can't expect strangers to be of any help, can you? All we can say is that your Java callback code executed one of `wait`, `notify`, or `notifyAll` without holding the target's monitor, or even directly instantiated and threw `IllegalMonitorStateException`. That information is quite useless to you, I presume. – Marko Topolnik Sep 06 '14 at 10:00
  • Time to hit this question with the close hammer, I think. The OP is not getting the message. – Stephen C Sep 06 '14 at 10:04
  • @MarkoTopolnik There is no `wait/notify/notifyAll` that's what's confusing me. – atoMerz Sep 06 '14 at 10:15
  • But you are clueless as to which line of your Java callback actually throws the exception? Why don't you try eliminating all possible suspects by commenting them out? – Marko Topolnik Sep 06 '14 at 10:18
  • @MarkoTopolnik Correct, I don't know what line of code throws the exception I have only been able to trace it (by logging) to the point said in the question. I cannot go further since it will go in JVM code. What I suspect is that something in maybe the JVM is trying to work in a synchronized block, (When it is instantiating the new thread/runnable). – atoMerz Sep 06 '14 at 10:25
  • You have positively concluded that the line `new Thread(...).start()` throws the exception? Have you studied the documentation as to any restrictions about what Java code called from native code is allowed to do? – Marko Topolnik Sep 06 '14 at 10:37
  • You could also catch the exception in the native code and try to get its stacktrace. – Marko Topolnik Sep 06 '14 at 10:43
  • @MarkoTopolnik Yes, that is my best guess: Somewhere in creating the `new Runnable()` the exception occurs. I cannot catch the exception in c++ since the function returns normally (Whether I catch the exception in java or not it is not passed to c++). – atoMerz Sep 06 '14 at 11:08
  • You have isolated the `new Thread()` constructor code and `Thread.start()` code, pinpointing the problem to `new Runnable()` constructor code? That would be my last-resort guess. Both the `Thread` constructor and `start()` are complex methods with a lot going on, and `start` of course calling again back into native code to start a new native thread. The `Runnable` constructor is probably almost a no-op. – Marko Topolnik Sep 06 '14 at 11:12
  • @MarkoTopolnik I posted a workaround and a possible cause, any comments? – atoMerz Sep 07 '14 at 15:59
  • Well, nothing much to add, you've got a mess of threads and java-native transitions. I have never done similar work so I have no experience to share with you. – Marko Topolnik Sep 07 '14 at 16:21

1 Answers1

1

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.

atoMerz
  • 7,534
  • 16
  • 61
  • 101