JNI - Java exits before native threads finish executing - java

I'm in the early stages of developing an API in C++, which I'm wrapping in Java using JNI. The native code creates a socket listener thread using WinAPI which should run indefinitely, thereby keeping the program open indefinitely (tested and works fine).
However, when I try to invoke this code in Java, the JVM still terminates when it reaches the end of main, ignoring the running thread. A little research has hinted that Java might think the thread is a daemon rather than a "user thread". But if that's the case, then I can't quite figure out how to convince Java that it actually is a user thread.
Does anyone have a clue about this?

You need to call AttachCurrentThread() for all your native threads, to ensure Java knows about them, so it will wait for them to finish.

Windows doesn't have daemon threads. The process exits when ExitProcess() is called or when the initial thread returns from the application's main function. (In principle, it will also exit if the last thread exits, but that can't be relied upon because Windows may create threads in your process that you don't know about.)
The Java runtime presumably waits for all of its own threads to exit (except for those that it considers daemon threads) before exiting the process. But your threads were created directly via the Win32 API, so Java doesn't know about them and therefore won't wait for them.
If your API wants to continue performing some task beyond the natural lifetime of the calling process, it should probably create a child process rather than a thread. (Or, if the API is Java-specific, it can presumably make use of JNI to ask that Java create the thread on its behalf, or to register the thread with Java.)

Related

Command to Interrupt a hung thread running in a java process without code changes

I've a java process running and unfortunately one thread inside the process is hung.
I found the Thread id which was hung using jstack, however I was unable to find any references on how to interrupt this thread using the id?
Is it possible to Interrupt/Stop a thread from console (or basically outside the process) by using the processId and ThreadId?
Any suggestions on how to tackle this?
PS : I don't want to kill the process as its just one thread which is hung. Also, neither do I want to make code changes to Stop/Interrupt the thread. I just want to kill it, so all its resources can be released.
There's no baked-in way to kill a thread within the JVM, at least not a deliberately implemented one.
Having said that, if you have started your JVM with the appropriate parameters, so that you can start a remote JMX session to it, you can actually suspend the thread and inject a RuntimeException into it, which will almost surely terminate it (unless you are doing something gnarly with RuntimeExceptions in it).
See this blogpost.
P.S. You would never start your JVM in production allowing rogue JMX connections though, and if you're not in production, I'd guess that the above approach is not of much help to you.

Proper shutdown of JVM when launching from C++

I'm launching JVM from C++ code via JNI. I have a problem that when just quitting my C++ process it seems some shutdown hooks from JVM are not run, and therefore some temp resources are still being around, that in my particular case prevents launching JVM next time I open a C++ process.
I tried jvm->DestroyJavaVM(), but after all my process windows were closed, I still could see the process running. What's the best wait to ensure that the JVM is shut down properly when launched via JNI?
Thanks!
First of all, jvm->DestroyJavaVM() won't return till all non-daemon jvm threads have stopped, it does nothing but waiting for them to stop, so you should stop them in java.
Secondly, System.exit will cause the whole process to be shut down.
So what you really need is check your java code that which thread is not stopped yet, for example the background message loop thread of the ui framework such as gwt or swing.
The easiest way is to call System.exit via JNI.

Using existing Thread for Java AWT

Is there a way to use a existing Thread (especially the main Thread) for AWT windows. I am currently opening a Frame which then handles everything and the main Thread is just paused and waits for the window to close. For me this seems like a (not very devastating) waste of resources, so I would appreciate only using the main Thread for AWT. Is there a good reason why this isn't done and if not, is there a way to do it?
Just let the main thread exit, there is no need to keep it paused and waiting around.
Threads can be marked as Daemon or not. The application only exits when every non-daemon thread has exited, in Java the Main thread doesn't really have any special significance beyond the fact it is started first.
The EDT thread is not a Daemon thread so it will keep the application alive by itself.
What is Daemon thread in Java?
Based on this documentation http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html
When a Java Virtual Machine starts up, there is usually a single non-daemon thread (which typically calls the method named main of some designated class). The Java Virtual Machine continues to execute threads until either of the following occurs:
The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place.
All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception that propagates beyond the run method.
moral of the story :
A Java program will wait for all non-daemon threads to finish first.
In your case you might wanna exit the main thread.
One paused thread (if it's even actually paused) isn't really a big deal. I suggest looking at your program in something like JProfiler, you'll be shocked at what's going on in the background.

Is there a way to force a native thread to exit through JNI?

I have a program that's using the FFMPEG binary libraries via JNI. There is a call to open a URL which is blocking in native code, and I need to allow the user to manually cancel this connection. Sometimes Thread.interrupt() works just like it's supposed to (if the url I'm connecting to is "udp://{whatever}"). If my URL is "rtp://{whatever}", Thread.interrupt() doesn't appear to be honored by the native thread. Thread.kill() doesn't even seem to do it (and is generally frowned on anyhow).
Does anyone know a different way to interrupt or kill a native thread through JNI?
Take a look at how Xuggle does this (a JNI wapper to FFmpeg). Everytime FFmpeg calls it's interrupt callback, Xuggler calls into Java to see if the thread was interrupted, and if so, returns true.
The native code can regularly check the thread to see if it's interrupted, just as Java code does.
Another approach is operating-system-specific, but you can send you thread a signal and that signal can set a flag - this may be more straightforward for the JNI-side to check.
All thread-stopping is cooperative - you tell the thread to stop by setting a flag (via Thread.interrupt() or a flag set in a signal handler - and the thread code checks this often.

Java threads: Is it possible view/pause/kill a particular thread from a different java program running on the same JVM?

I have a program 'foo' running different threads, fooT1, fooT2, .. fooTn.
Now if I want write another program 'bar', which could kill the thread fooTr, is that possible?
Reason: One of the thread fooTr tracks product license. If this thread is killed; one may run this product indefinitely. And killing 'foo' itself is tolerable as 'foo' as that is exactly what is being done on license expiry.
System: Fedora Distribution of Linux
Note: The commands which start JVM and program foo are placed in /etc/init.d and anyone who has a decent knowledge of rc.1/rc.2/rc.3 structure can change/add the starting parameters to these.
I hope my question is clear. If not, I can always edit it.
Actually the java debugger will allow you to kill a thread by injecting an exception into it. I was just trying to work out how to use this feature to kill a thread without wiping out the whole jvm, when I came across this question. If you run the jvm with command line options like:
java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8888 your.app.Main
and connect the debugger with something like:
jdb -attach 127.0.0.1:8888
you can type:
threads
to get a list of the running threads, and use the kill command to kill a running thread. The bit I'm currently not sure about is the syntax of this kill command, I have tried the obvious:
kill 0xe2e new java.lang.IllegalArgumentException("er");
and I get the messages:
killing thread: Swank REPL Thread
Thread not suspended
Expression must evaluate to an object
("Swank REPL Thread" is the thread I want to kill, and yes, I've tried suspending it first ;)
Still my inability to use the java debugger aside, it looks to me like a thread can be killed at random. Maybe you can just make sure you ignore all exceptions and keep running and that will be enough, but I'm not sure about that.
To my knowledge it is not possible to do this directly. What you could consider however is to create some kind of service on your 'foo' that can be called from 'bar' to kill the thread. There are, of course, hundreds of ways to implement this. My first thought would be to do this using RMI.
You could do this even without a separate application. Write your own startup class, which performs a pass-through of parameters to the original startup class of the application. Your class's main method though would create a thread that periodically checks the list of all threads (e.g., Thread.getAllStackTraces or Thread.enumerate), finds the offending thread, and invokes stop() on it. Although Thread.stop is deprecated, it still works.
Another option is to run the application under a Java debugger, say, jdb and then suspend/kill the required thread. You could also add parameters to the application's startup so that the JVM can be attached to, then attach jdb to the running JVM and suspect/kill the thread.
Until now isnĀ“t possible to run to diferent programs in the same JVM, but some people is investigating it, in order to reduce the startup time and the memory and cpu usage of diferent java programs runing in the same machine

Categories

Resources