Loading a windows keystore(Windows-MY) which contains a token based key is leaving the java process as a background process.
I had registered a shutdown hook, the hook is getting executed and Visual VM is reporting the application is terminated, but the ports opened by the process is not released(like jmx port) unless the process is terminated explicitly using task manager.
A very simple test case used is as below, but to test the case you have to plugin a key token.
public static void main(String[] args) throws Exception {
KeyStore keyStore = KeyStore.getInstance("Windows-MY");
keyStore.load(null, null);
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
System.out.println("Close");
}
});
//System.exit(1); even with explicit call to exit nothing is happening
}
Edit: Looks like giving the example of ports have done more harm than good. I gave the example of the jmx port as just an example for the fact that the original process was not terminated. If the processes is terminated then the ports are released.
Related
I created a class that starts and ends a process in java. I tried mspaint.exe with or without args and it starts the process,
but when I tried to start calculator(calc.exe) it doesn't work.
Is there a reason it will only start specific processes?
public class XProcess {
private Process process;
private String cmd;
public XProcess(String command) {
this.cmd = command;
}
public synchronized void start() throws IOException{
process = Runtime.getRuntime().exec(this.cmd);
}
public synchronized void destroy(){
process.destroy();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException, InterruptedException {
XProcess process = new XProcess("mspaint.exe");
process.start();
Thread.sleep(5000);
process.destroy();
}
}
The javadoc for Process's destroy() explains it quite nicely
Kills the subprocess. Whether the subprocess represented by this
Process object is forcibly terminated or not is implementation
dependent.
Generally, an attempt to destroy (or kill) a process is a request. The Operating System could intercept the request, or the process itself could refuse the request.
The proper way to shutdown a process is for the process to internally quit, with the parent process (the one that launched the child process) listening for the child's exit. Anything else tends to be spotty as to whether it will work in all cases, with all processes.
This is why many processes (Tomcat is an example) accept a shutdown command as a network request, so it can then handle the request, shutting down internally.
Are you using some recent Windows? 10 or probably even 8?
Then it's unrelated to Java, the new Calculator is a Windows Store app, calc.exe is probably just a wrapper that starts it in a new container process and exists right after that, it's gone by the time you try to destroy it.
How do I stop a Java process gracefully in Linux and Windows?
When does Runtime.getRuntime().addShutdownHook get called, and when does it not?
What about finalizers, do they help here?
Can I send some sort of signal to a Java process from a shell?
I am looking for preferably portable solutions.
Shutdown hooks execute in all cases where the VM is not forcibly killed. So, if you were to issue a "standard" kill (SIGTERM from a kill command) then they will execute. Similarly, they will execute after calling System.exit(int).
However a hard kill (kill -9 or kill -SIGKILL) then they won't execute. Similarly (and obviously) they won't execute if you pull the power from the computer, drop it into a vat of boiling lava, or beat the CPU into pieces with a sledgehammer. You probably already knew that, though.
Finalizers really should run as well, but it's best not to rely on that for shutdown cleanup, but rather rely on your shutdown hooks to stop things cleanly. And, as always, be careful with deadlocks (I've seen far too many shutdown hooks hang the entire process)!
Ok, after all the possibilities I have chosen to work with "Java Monitoring and Management"
Overview is here
That allows you to control one application from another one in relatively easy way. You can call the controlling application from a script to stop controlled application gracefully before killing it.
Here is the simplified code:
Controlled application:
run it with the folowing VM parameters:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
//ThreadMonitorMBean.java
public interface ThreadMonitorMBean
{
String getName();
void start();
void stop();
boolean isRunning();
}
// ThreadMonitor.java
public class ThreadMonitor implements ThreadMonitorMBean
{
private Thread m_thrd = null;
public ThreadMonitor(Thread thrd)
{
m_thrd = thrd;
}
#Override
public String getName()
{
return "JMX Controlled App";
}
#Override
public void start()
{
// TODO: start application here
System.out.println("remote start called");
}
#Override
public void stop()
{
// TODO: stop application here
System.out.println("remote stop called");
m_thrd.interrupt();
}
public boolean isRunning()
{
return Thread.currentThread().isAlive();
}
public static void main(String[] args)
{
try
{
System.out.println("JMX started");
ThreadMonitorMBean monitor = new ThreadMonitor(Thread.currentThread());
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("com.example:type=ThreadMonitor");
server.registerMBean(monitor, name);
while(!Thread.interrupted())
{
// loop until interrupted
System.out.println(".");
try
{
Thread.sleep(1000);
}
catch(InterruptedException ex)
{
Thread.currentThread().interrupt();
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
// TODO: some final clean up could be here also
System.out.println("JMX stopped");
}
}
}
Controlling application:
run it with the stop or start as the command line argument
public class ThreadMonitorConsole
{
public static void main(String[] args)
{
try
{
// connecting to JMX
System.out.println("Connect to JMX service.");
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
// Construct proxy for the the MBean object
ObjectName mbeanName = new ObjectName("com.example:type=ThreadMonitor");
ThreadMonitorMBean mbeanProxy = JMX.newMBeanProxy(mbsc, mbeanName, ThreadMonitorMBean.class, true);
System.out.println("Connected to: "+mbeanProxy.getName()+", the app is "+(mbeanProxy.isRunning() ? "" : "not ")+"running");
// parse command line arguments
if(args[0].equalsIgnoreCase("start"))
{
System.out.println("Invoke \"start\" method");
mbeanProxy.start();
}
else if(args[0].equalsIgnoreCase("stop"))
{
System.out.println("Invoke \"stop\" method");
mbeanProxy.stop();
}
// clean up and exit
jmxc.close();
System.out.println("Done.");
}
catch(Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
That's it. :-)
An another way: your application can open a server socet and wait for an information arrived to it. For example a string with a "magic" word :) and then react to make shutdown: System.exit(). You can send such information to the socke using an external application like telnet.
Here is a bit tricky, but portable solution:
In your application implement a shutdown hook
When you want to shut down your JVM gracefully, install a Java Agent that calls System.exit() using the Attach API.
I implemented the Java Agent. It is available on Github: https://github.com/everit-org/javaagent-shutdown
Detailed description about the solution is available here: https://everitorg.wordpress.com/2016/06/15/shutting-down-a-jvm-process/
Similar Question Here
Finalizers in Java are bad. They add a lot of overhead to garbage collection. Avoid them whenever possible.
The shutdownHook will only get called when the VM is shutting down. I think it very well may do what you want.
Thanks for you answers. Shutdown hooks seams like something that would work in my case.
But I also bumped into the thing called Monitoring and Management beans:
http://java.sun.com/j2se/1.5.0/docs/guide/management/overview.html
That gives some nice possibilities, for remote monitoring, and manipulation of the java process. (Was introduced in Java 5)
Signalling in Linux can be done with "kill" (man kill for the available signals), you'd need the process ID to do that. (ps ax | grep java) or something like that, or store the process id when the process gets created (this is used in most linux startup files, see /etc/init.d)
Portable signalling can be done by integrating a SocketServer in your java application. It's not that difficult and gives you the freedom to send any command you want.
If you meant finally clauses in stead of finalizers; they do not get extecuted when System.exit() is called.
Finalizers should work, but shouldn't really do anything more significant but print a debug statement. They're dangerous.
How do I stop a Java process gracefully in Linux and Windows?
When does Runtime.getRuntime().addShutdownHook get called, and when does it not?
What about finalizers, do they help here?
Can I send some sort of signal to a Java process from a shell?
I am looking for preferably portable solutions.
Shutdown hooks execute in all cases where the VM is not forcibly killed. So, if you were to issue a "standard" kill (SIGTERM from a kill command) then they will execute. Similarly, they will execute after calling System.exit(int).
However a hard kill (kill -9 or kill -SIGKILL) then they won't execute. Similarly (and obviously) they won't execute if you pull the power from the computer, drop it into a vat of boiling lava, or beat the CPU into pieces with a sledgehammer. You probably already knew that, though.
Finalizers really should run as well, but it's best not to rely on that for shutdown cleanup, but rather rely on your shutdown hooks to stop things cleanly. And, as always, be careful with deadlocks (I've seen far too many shutdown hooks hang the entire process)!
Ok, after all the possibilities I have chosen to work with "Java Monitoring and Management"
Overview is here
That allows you to control one application from another one in relatively easy way. You can call the controlling application from a script to stop controlled application gracefully before killing it.
Here is the simplified code:
Controlled application:
run it with the folowing VM parameters:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
//ThreadMonitorMBean.java
public interface ThreadMonitorMBean
{
String getName();
void start();
void stop();
boolean isRunning();
}
// ThreadMonitor.java
public class ThreadMonitor implements ThreadMonitorMBean
{
private Thread m_thrd = null;
public ThreadMonitor(Thread thrd)
{
m_thrd = thrd;
}
#Override
public String getName()
{
return "JMX Controlled App";
}
#Override
public void start()
{
// TODO: start application here
System.out.println("remote start called");
}
#Override
public void stop()
{
// TODO: stop application here
System.out.println("remote stop called");
m_thrd.interrupt();
}
public boolean isRunning()
{
return Thread.currentThread().isAlive();
}
public static void main(String[] args)
{
try
{
System.out.println("JMX started");
ThreadMonitorMBean monitor = new ThreadMonitor(Thread.currentThread());
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("com.example:type=ThreadMonitor");
server.registerMBean(monitor, name);
while(!Thread.interrupted())
{
// loop until interrupted
System.out.println(".");
try
{
Thread.sleep(1000);
}
catch(InterruptedException ex)
{
Thread.currentThread().interrupt();
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
// TODO: some final clean up could be here also
System.out.println("JMX stopped");
}
}
}
Controlling application:
run it with the stop or start as the command line argument
public class ThreadMonitorConsole
{
public static void main(String[] args)
{
try
{
// connecting to JMX
System.out.println("Connect to JMX service.");
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
// Construct proxy for the the MBean object
ObjectName mbeanName = new ObjectName("com.example:type=ThreadMonitor");
ThreadMonitorMBean mbeanProxy = JMX.newMBeanProxy(mbsc, mbeanName, ThreadMonitorMBean.class, true);
System.out.println("Connected to: "+mbeanProxy.getName()+", the app is "+(mbeanProxy.isRunning() ? "" : "not ")+"running");
// parse command line arguments
if(args[0].equalsIgnoreCase("start"))
{
System.out.println("Invoke \"start\" method");
mbeanProxy.start();
}
else if(args[0].equalsIgnoreCase("stop"))
{
System.out.println("Invoke \"stop\" method");
mbeanProxy.stop();
}
// clean up and exit
jmxc.close();
System.out.println("Done.");
}
catch(Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
That's it. :-)
An another way: your application can open a server socet and wait for an information arrived to it. For example a string with a "magic" word :) and then react to make shutdown: System.exit(). You can send such information to the socke using an external application like telnet.
Here is a bit tricky, but portable solution:
In your application implement a shutdown hook
When you want to shut down your JVM gracefully, install a Java Agent that calls System.exit() using the Attach API.
I implemented the Java Agent. It is available on Github: https://github.com/everit-org/javaagent-shutdown
Detailed description about the solution is available here: https://everitorg.wordpress.com/2016/06/15/shutting-down-a-jvm-process/
Similar Question Here
Finalizers in Java are bad. They add a lot of overhead to garbage collection. Avoid them whenever possible.
The shutdownHook will only get called when the VM is shutting down. I think it very well may do what you want.
Thanks for you answers. Shutdown hooks seams like something that would work in my case.
But I also bumped into the thing called Monitoring and Management beans:
http://java.sun.com/j2se/1.5.0/docs/guide/management/overview.html
That gives some nice possibilities, for remote monitoring, and manipulation of the java process. (Was introduced in Java 5)
Signalling in Linux can be done with "kill" (man kill for the available signals), you'd need the process ID to do that. (ps ax | grep java) or something like that, or store the process id when the process gets created (this is used in most linux startup files, see /etc/init.d)
Portable signalling can be done by integrating a SocketServer in your java application. It's not that difficult and gives you the freedom to send any command you want.
If you meant finally clauses in stead of finalizers; they do not get extecuted when System.exit() is called.
Finalizers should work, but shouldn't really do anything more significant but print a debug statement. They're dangerous.
I'm trying to simulate tests of various run-throughs of my program, setting up a Jetty server in a #Before method and closing it down in an #After.
My first test will run successfully, but upon attempting to POST data in following tests com.sun.jersey.api.client.ClientHandlerException: java.net.SocketException: Software caused connection abort: recv failed occurs. Is there any way I can get my Server (and Client?) to shut down cleanly between tests?
My Before and After code is as follows:
#Before
public void startServer() {
try {
server = new Server(8080);
ServletContextHandler root = new ServletContextHandler(server, "/ingest", ServletContextHandler.SESSIONS);
root.addServlet(new Servlet(), "/*");
server.start();
client = new Client();
client.setChunkedEncodingSize(16 * 1024);
FileInputStream stream = new FileInputStream(testFile);
try {
client.resource(uri).type(MediaType.APPLICATION_OCTET_STREAM).post(stream);
} catch (Exception e) {
e.printStackTrace();
} finally {
Closeables.closeQuietly(stream);
client.destroy();
}
} catch (Exception e) {
e.printStackTrace();
fail("Unexpected Exception when starting up server.");
}
}
#After
public void shutDown() {
if (output.exists()) {
output.delete();
}
try {
server.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
Best practice in testing scenarios is to not hard code the port. That only leads to conflicts when running elsewhere, especially on CI systems that have even a moderate load or variety of projects.
in Jetty 9 (same idea in 6, 7, 8)
_server = new Server();
_connector = new ServerConnector(_server);
_server.setConnectors(new Connector[] { _connector });
_server.start();
int port = _connector.getLocalPort();
It turns out that what I had was in fact working, however due to the asynchronous nature of the server.stop(), my new server was attempting to instantiate before the previous server's shut down thread had completely executed.
A simple Thread.sleep(n) after the server.stop() gives the server the time it needs to shut down between tests. Unfortunately, the server seems to prematurely claim that it has stopped thus preventing an exact solution through checking the server state - but perhaps there is something to poll on the server; possibly examining the thread pool could provide a consistent result?
In any case, as this is only for testing purposes, merely starting the server in the #BeforeClass and shutting it down in #AfterClass prevents the whole server shut down kerfuffle, but beware of then starting another server on the same port in your test suite.
My guess is that it was getting a port conflict. We actually do this for our tests, and surprisingly the performance hit isn't that bad. We began by starting a single server before all tests as the answer suggests, but we had to switch to support mutation testing. One downside to relying on Maven is that you have to start it up on the side to run a single test in an IDE.
For anyone interested, our implementation is here: embedded-test-jetty. It runs multiple servers at once on different ports(for parallel testing), checks port availability, supports SSL, etc.
I handle this using a couple of things. First, after each test, make sure your server is shutdown, and join() on it. Either do this in #After or #AfterClass depending on what you are doing.
server.stop();
server.join();
Next, before each test, make sure the port is available. I use the snippet available at Sockets: Discover port availability using Java
Then, the setup code becomes
public static void waitForPort(int port) {
while( !available(port) ) {
try { Thread.sleep(PORT_SLEEP_MILLIS); }
catch (InterruptedException e) {}
}
}
#Before
public void setUp() throws Exception {
waitForPort(9876);
waitForPort(9877);
// Make sure the ports are clear
Thread.sleep(500);
}
The little extra sleep at the end ensures that the port is available; because just checking that it is available might make the system not reuse it. Another option is to just set SO_REUSEADDR when you are opening the port after having checked it.
Try:
server = new Server();
SocketConnector connector = new SocketConnector();
connector.setPort(8080);
server.setConnectors(new Connector[] { connector });
WebAppContext context = new WebAppContext();
context.setServer(server);
context.setContextPath("/your-context");
context.setWar("path to war");
server.addHandler(context);
Thread monitor = new MonitorThread();
monitor.start();
server.start();
server.join();
then somewhere you say:
server.stop()
Helpful article:
http://www.codeproject.com/Articles/128145/Run-Jetty-Web-Server-Within-Your-Application
I realise that this doesn't directly answer your question... but starting and stopping a server in #Before and #After methods is inefficient when you have more than one integration test that requires a server to be running, as the server would be restarted for every test.
You may want to consider starting and stopping your server around your entire suite of tests. If you are using Maven for builds, you can do this with the combination of failsafe and Jetty plugins.
I'm now using LocateRegistry.createRegistry(1099) rathern than using the registry in a external process. However the registry dies after the main program ends. For instance, if I make a simple program that creates the registry it'll not work because after the main executino the code ends. I was expecting the LocateRegistry code to create a thread, but it seems that this is not the case. Is this the normal behavior of using LocateRegistry or I'm missing something?
Code sample:
// ommited imports
public class RMITest {
public static void main(String[] args) {
LocateRegistry.createRegistry(1099);
// JVM will exit now!!!
}
}
The RMI Server start and suddenly dies. How
I was expecting the LocateRegistry code to create a thread
It's not that simple.
Exporting the first object on a new port creates a thread that listens on that port, and unexporting the last object listening on a port causes that thread to exit. This is for all remote objects, not just local Registry objects.
Unexporting can happen automatically via local GC, which in turn can be trigged by remote DGC.
Your JVM exits because you aren't saving the value returned by LocateRegistry.createRegistry() in a static variable, so it gets GC'd, so the object gets unexported, so there are no remote objects exported on port 1099, so the thread that listens on 1099 exits, so there are no non-daemon threads, so the JVM exits.
Solution: store the result of LocateRegistry.createRegistry() in a static variable. You can use that to unexport the Registry when you want your JVM to exit.
There are two possible ways to start the RMI registry.
LocateRegistry.createRegistry(1099); The java application executing the registry must not finish. In your case you could start a new "never ending" thread (see below for source code)
rmiregistry This is a tool included in the java distribution that starts an RMI registry service. see rmiregistry - The Java Remote Object Registry
Sample code for RMI registry server.
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
public class RmiTest {
public static void main(String[] args) throws IOException {
final Object monitor = new Object();
new Thread(new Runnable() {
public void run() {
try {
LocateRegistry.createRegistry(1099);
synchronized (monitor) {
monitor.wait();
}
} catch (RemoteException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("RMI Registry Thread finished.");
}
}, "RMI Registry Thread").start();
System.out.println("Press enter to exit...");
System.in.read();
synchronized (monitor) {
monitor.notify();
}
}
}
LocateRegistry.createRegistry(1099);
creates a new daemon thread named RMI TCP Accept-1099 on my machine. This thread essentially listens for new TCP/IP connections on 1099.
Daemon threads are automatically killed when JVM exits. And in your case JVM exits when you leave main() method. More precisely - it exits when there are no more non-daemon threads - and apparently there is only one non-daemon thread in your application (named main).
So you have two options:
don't let main() method to finish by adding infinite sleep().
create some non-daemon thread. Of course only do this when the thread actually does something useful rather than preventing JVM to exit.