I have a Windows MFC application that:
(1) Loads the JVM (JNI_CreateJavaVM())
(2) Attaches the main thread to the JVM (AttachCurrentThread())
(3) Loads some Java classes and methods (FindClass() and GetMethodID() / GetStaticMethodID())
(4) Registers some native callbacks for use by Java code (RegisterNatives())
(5) Detaches the thread from JVM (DetachCurrentThread())
(6) Destroys the JVM (DestroyJavaVM())
All of the above functions succeed every other time I run the application. I know they succeed, because, additionally to the above, I interact with the application and successfully call Java static methods, and these Java methods successfully call my native callbacks. My application exits gracefully, and it is certain that the expected Java functions, and native callbacks, have been executed.
However, every other time that I run the application, the call to JNI_CreateJavaVM() fails (not populating the JavaVM *). Absolutely nothing changes between runs of the application. I simply run it once (successfully, even without doing anything except the above 6 steps), quit gracefully, run again, and it fails, back and forth. There are no exceptions to the back-and-forth success/failure - I can run it dozens of times, and it oscillates precisely every other time between success, and failing on the JNI_CreateJavaVM() line.
If necessary, I will paste more code. However, I hope somebody has an insight with what I've provided. (Note: this is a BCGSoft MFC property-sheet application, though I strongly doubt that matters.)
It looks like you are running into this bug (restated here) that is probably never going to be fixed.
Despite its name, DestroyJavaVM() does not actually destroy the JVM. What it does is signal the JVM that it should shut down, but the JVM actually waits until all the threads other than the Main thread have stopped before it actually shuts down. In fact, even then it does not fully clean up after itself, as the documentation states (quite cryptically): "The JDK/JRE still does not support VM unloading, however."
Also, I'm concerned about your step 2, "Attaches the main thread to the JVM". You do not need to attach the thread that created the JVM to the JVM and you may not detach that thread. If you really are doing that, then it's possible that is what is messing up your system. (The thread that creates the JVM is the JVM's "Main" thread. You only need to attach/detach other native threads to the JVM if they need access to it.)
By the way, JNI_CreateJavaVM() returns 0 on success, and you say it returns 0 the "failed" times, so in what sense is it failing? Which JVM (version, vendor) are you using?
Related
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.)
When a JVM-ran (written in Scala actually, but I tend to believe that the solution is going to be pretty much the same for Groovy, Clojure or pure Java) console program of mine gets terminated by the user pressing Ctrl+C (or by the system shut-down sequence, I don't know if there is any difference for a program), how do I make sure the external resources the application modifies (databases, files, web service abstracted resources) are left in a predictable, non-logically-corrupt state?
You can try to implement a shutdown hook as others pointed BUT:
In rare circumstances the virtual machine may abort, that is, stop
running without shutting down cleanly. This occurs when the virtual
machine is terminated externally, for example with the SIGKILL signal
on Unix or the TerminateProcess call on Microsoft Windows. The virtual
machine may also abort if a native method goes awry by, for example,
corrupting internal data structures or attempting to access
nonexistent memory. If the virtual machine aborts then no guarantee
can be made about whether or not any shutdown hooks will be run.
I guess, you would have to introduce transactional context into your application I believe. For databases that's quite easy, for file system you can look into Apache Commons Transaction
Take a look at Runtime.addShutdownHook.
You would typically use it as so:
Runtime.addShutdownHook(new Thread() {
public void run() {
// do your clean up here.
}
});
You can trap this signal and close off resources. Most services do not need to be closed gracefully, however files you write to usually do.
It is possible just adding a shutdown hook is all you need. But I would test this for your situation.
Where I work they use the AppletContext.showDocument(URL) method when a user logs off our application, which is an applet, providing the desired logoff JSP. But they also have code that says if for some reason they are unable to get an AppletContext to simply call the Applet.destroy() method.
We are using a thin client architecture which means that we essentially have a bunch of dumb terminals connected to a server. I mention this because we will often have dozens if not 100's of instances of JVMs running - one for each applet.
Inside the destroy() method they dispose of all resources they acquired and then get a reference to Runtime and call runFinalization() and gc() - but it does not do a System.exit() or equivalent.
Questions
I understand that frees up resources and leaves you on the same web page but what does it do to the JVM that was running the applet?
If I add a call to System.exit() at the end of the destroy() what will it do to the other JVMs that are running on the thin client server?
For context, this is all necessary because while a page is active browsers (or the Java plugin, or both) hang on to your applet instance. Even if you remove it from the DOM or try other tricks to release that memory, until you navigate to a different page your applet instance is retained so you need to fully clean up in destroy(). I've done memory profiling which shows it's referenced in native code somewhere.
To answer your questions:
This depends on your version of Java. As of Java 6 update 10 (with the next-gen plugin) after a period of time with no applets running Java will shut itself down. This timeout has appeared to get shorter as the JVM startup time has decreased in the last year or two.
I don't believe applets (even signed ones) are allowed to call System.exit(). If it was allowed though, on modern browsers it would kill the instance of the JVM for that browser, none of the others. In the past it would've been likely to shut the entire browser down :)
EDIT:
Actually there's more to the story of Answer 1... that's true everywhere except OS X, where the next-gen plugin wasn't the default until somewhere around 6u27 (On 10.6 it was Java for OS X update 5, and 10.7 from day 1).
I'm developing an artificial intelligent program to explore a given space for resources.
I'd like to run multiple scenarios in order to collect data and output to a file.
I used the "multiple runs" option in the gui and i do stop() when one module run is finished (all the resources have been explored). The problem is when It runs the model a second turn, it doesn't work properly.
What I mean is that after running once I always need to kill the application by exiting because the restart option doesn't work properly.
Is there anything that "restart" forgets to do? Because if I exit the application and run it again it works perfectly
Edited so it's more clear:
I use the Repast platform in order to simulate an exploration to Mars. I have 3 kinds of agents, scouting, digging and transporting. They communicate among them to schedule tasks and other things.
The first time I run the simulation everything runs smoothly. And when all the mineral resources of the planet have been explored I restart the model and try again so I can collect data.
The problem is, when I use the "restart" option the Simulation doesn't run well. But if I exit (not restart) and run it again it works fine.
What I'd like to know is if the restart option of Repast GUI misses any steps..
Thanks in advance
PS: If you guys think that it's absolutely necessary I can post some code...but the project is quite big
Don't use Thread.stop() method. It is deprecated. Thread.stop is being deprecated because it is inherently unsafe. Stopping a thread causes it to unlock all the monitors that it has locked. (The monitors are unlocked as the ThreadDeath exception propagates up the stack.) If any of the objects previously protected by these monitors was in an inconsistent state, other threads might view these objects in an inconsistent state. Such objects are said to be damaged. Threads operating on damaged objects can behave arbitrarily, either obviously or not. Unlike other unchecked exceptions, ThreadDeath kills threads silently; thus, the user has no warning that the program may be corrupted. The corruption can manifest itself at an unpredictable time after the damage occurs. Substitute any use of Thread.stop with code that provides for a gentler termination.
http://docs.sun.com/app/docs/doc/805-4031/6j3qv1of1?a=view
Consider thread stopping either via Thread.interrupt() or via setting cancel flag. Look at Java Concurrency in Practice, Section 7.1. Task Cancellation.
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