xico 0 Report post Posted July 29, 2008 See the next few lines containing Java Code: 1. // imports 2. import sun.management.ConnectorAddressLink; 3. import sun.jvmstat.monitor.HostIdentifier; 4. import sun.jvmstat.monitor.Monitor; 5. import sun.jvmstat.monitor.MonitoredHost; 6. import sun.jvmstat.monitor.MonitoredVm; 7. import sun.jvmstat.monitor.MonitoredVmUtil; 8. import sun.jvmstat.monitor.MonitorException; 9. import sun.jvmstat.monitor.VmIdentifier; 10. 11. public static void main(String args[]) { 12. /* The method ManagementFactory.getRuntimeMXBean() returns an identifier with applcation PID 13. in the Sun JVM, but each jvm may have you own implementation. 14. So in anothers jvm, other than Sun, this code may not work., :( 15. */ 16. RuntimeMXBean rt = ManagementFactory.getRuntimeMXBean(); 17. final int runtimePid = Integer.parseInt(rt.getName().substring(0,rt.getName().indexOf("@"))); 18. 19. java.awt.EventQueue.invokeLater(new Runnable() { 20. public void run() { 21. 22. // If exists another instance, show message and terminates the current instance. 23. // Otherwise starts application. 24. if (getMonitoredVMs(runtimePid)) 25. { 26. new MainFrame().setVisible(true); 27. } else 28. JOptionPane.showMessageDialog(null,"There is another instance of this application running."); 29. 30. } 31. }); 32. } This code above shows us how to implement a single instance application. But let me explain it.The getMonitoredVMs(int processPid) method receives as paramter the current application PID, and catch the application name that is called from command line, for example, the application was started from c:\java\app\test.jar path, then the value variable is "c:\\java\\app\\teste.jar". This way, we will catch just application name on the line 17 of the code below.After that, we search JVM for antoher process with the same name, if we found it and the application PID is different, it means that is the second application instance.1. private static boolean getMonitoredVMs(int processPid) { 2. MonitoredHost host; 3. Set vms; 4. try { 5. host = MonitoredHost.getMonitoredHost(new HostIdentifier((String)null)); 6. vms = host.activeVms(); 7. } catch (java.net.URISyntaxException sx) { 8. throw new InternalError(sx.getMessage()); 9. } catch (MonitorException mx) { 10. throw new InternalError(mx.getMessage()); 11. } 12. MonitoredVm mvm = null; 13. String processName = null; 14. try{ 15. mvm = host.getMonitoredVm(new VmIdentifier(String.valueOf(processPid))); 16. processName = MonitoredVmUtil.commandLine(mvm); 17. processName = processName.substring(processName.lastIndexOf("\\") + 1,processName.length()); 18. mvm.detach(); 19. } catch (Exception ex) { 20. 21. } 22. // This line is just to verify the process name. It can be removed. 23. JOptionPane.showMessageDialog(null,processName); 24. for (Object vmid: vms) { 25. if (vmid instanceof Integer) { 26. int pid = ((Integer) vmid).intValue(); 27. String name = vmid.toString(); // default to pid if name not available 28. try { 29. mvm = host.getMonitoredVm(new VmIdentifier(name)); 30. // use the command line as the display name 31. name = MonitoredVmUtil.commandLine(mvm); 32. name = name.substring(name.lastIndexOf("\\")+1,name.length()); 33. mvm.detach(); 34. if ((name.equalsIgnoreCase(processName)) && (processPid != pid)) 35. return false; 36. } catch (Exception x) { 37. // ignore 38. } 39. } 40. } 41. 42. return true; 43. }The problem of all this code are the imports, that are defined only in the file tools.jar file and has a size of 11MB. But to solve this problem, I have unpacked this file and a packed a new file called VM.ZIP only with the necessary classes, and it has a size of just 81kb.PS: When you're debbuging the code, the processName variable will be assigned to Class Main project, for example, the name of its class is Principal and is in the package com.main, then the variable processName will be assigned as "com.main.Principal." To test you have to open another instance of Debug and it will work.In the release case, it will be showed the application name as we can see in the line code JOptionPane.showMessageDialog(null,processName).Below the file attached VM.zip.VM.zip Share this post Link to post Share on other sites
prashant144 0 Report post Posted February 26, 2009 (edited) Hi, Its very nice yar. I also want the same thing but i use some different technique. 1. I make a ServerSocket object and capture a port say 1111 If again on another instance you are trying to make a same object then it is giving you error because your 1111 port is captured by 1st instance. So easily you can track and throw a error to user. Its very simple and effective too. Just follow the link for all codes.Single instance aaplicaion in JAVA2. Another method is make a txt file with one instance and delete while exiting. On next time just check if file is existing then any instance is running. And you can track the error. For being effective do not create file in C partition. Edited February 26, 2009 by prashant144 (see edit history) Share this post Link to post Share on other sites
zakaluka 0 Report post Posted April 10, 2009 I've used the lock method described by Prashant. The only problem is that the file has to be deleted manually if the application crashes without removing the lock.The benefit is that this technique works on every operating system and platform, with any java toolkit. I had a problem with capturing certain ports on unix, especially with certain firewalls running in the background.Regards,z. Share this post Link to post Share on other sites
prashant144 0 Report post Posted May 11, 2009 Hi Zakuluka,I am not tested in unix.If you have problem in capturing port then just make unique port like 99999 something like thatwhich nobody use.thanks I've used the lock method described by Prashant. The only problem is that the file has to be deleted manually if the application crashes without removing the lock.The benefit is that this technique works on every operating system and platform, with any java toolkit. I had a problem with capturing certain ports on unix, especially with certain firewalls running in the background.Regards,z. Share this post Link to post Share on other sites
nanaji 0 Report post Posted September 16, 2009 See the next few lines containing Java Code: 1. // imports 2. import sun.management.ConnectorAddressLink; 3. import sun.jvmstat.monitor.HostIdentifier; 4. import sun.jvmstat.monitor.Monitor; 5. import sun.jvmstat.monitor.MonitoredHost; 6. import sun.jvmstat.monitor.MonitoredVm; 7. import sun.jvmstat.monitor.MonitoredVmUtil; 8. import sun.jvmstat.monitor.MonitorException; 9. import sun.jvmstat.monitor.VmIdentifier; 10. 11. public static void main(String args[]) { 12. /* The method ManagementFactory.getRuntimeMXBean() returns an identifier with applcation PID 13. in the Sun JVM, but each jvm may have you own implementation. 14. So in anothers jvm, other than Sun, this code may not work., :( 15. */ 16. RuntimeMXBean rt = ManagementFactory.getRuntimeMXBean(); 17. final int runtimePid = Integer.parseInt(rt.getName().substring(0,rt.getName().indexOf("@"))); 18. 19. java.awt.EventQueue.invokeLater(new Runnable() { 20. public void run() { 21. 22. // If exists another instance, show message and terminates the current instance. 23. // Otherwise starts application. 24. if (getMonitoredVMs(runtimePid)) 25. { 26. new MainFrame().setVisible(true); 27. } else 28. JOptionPane.showMessageDialog(null,"There is another instance of this application running."); 29. 30. } 31. }); 32. } This code above shows us how to implement a single instance application. But let me explain it.The getMonitoredVMs(int processPid) method receives as paramter the current application PID, and catch the application name that is called from command line, for example, the application was started from c:\java\app\test.jar path, then the value variable is "c:\\java\\app\\teste.jar". This way, we will catch just application name on the line 17 of the code below.After that, we search JVM for antoher process with the same name, if we found it and the application PID is different, it means that is the second application instance.1. private static boolean getMonitoredVMs(int processPid) { 2. MonitoredHost host; 3. Set vms; 4. try { 5. host = MonitoredHost.getMonitoredHost(new HostIdentifier((String)null)); 6. vms = host.activeVms(); 7. } catch (java.net.URISyntaxException sx) { 8. throw new InternalError(sx.getMessage()); 9. } catch (MonitorException mx) { 10. throw new InternalError(mx.getMessage()); 11. } 12. MonitoredVm mvm = null; 13. String processName = null; 14. try{ 15. mvm = host.getMonitoredVm(new VmIdentifier(String.valueOf(processPid))); 16. processName = MonitoredVmUtil.commandLine(mvm); 17. processName = processName.substring(processName.lastIndexOf("\\") + 1,processName.length()); 18. mvm.detach(); 19. } catch (Exception ex) { 20. 21. } 22. // This line is just to verify the process name. It can be removed. 23. JOptionPane.showMessageDialog(null,processName); 24. for (Object vmid: vms) { 25. if (vmid instanceof Integer) { 26. int pid = ((Integer) vmid).intValue(); 27. String name = vmid.toString(); // default to pid if name not available 28. try { 29. mvm = host.getMonitoredVm(new VmIdentifier(name)); 30. // use the command line as the display name 31. name = MonitoredVmUtil.commandLine(mvm); 32. name = name.substring(name.lastIndexOf("\\")+1,name.length()); 33. mvm.detach(); 34. if ((name.equalsIgnoreCase(processName)) && (processPid != pid)) 35. return false; 36. } catch (Exception x) { 37. // ignore 38. } 39. } 40. } 41. 42. return true; 43. }The problem of all this code are the imports, that are defined only in the file tools.jar file and has a size of 11MB. But to solve this problem, I have unpacked this file and a packed a new file called VM.ZIP only with the necessary classes, and it has a size of just 81kb.PS: When you're debbuging the code, the processName variable will be assigned to Class Main project, for example, the name of its class is Principal and is in the package com.main, then the variable processName will be assigned as "com.main.Principal." To test you have to open another instance of Debug and it will work.In the release case, it will be showed the application name as we can see in the line code JOptionPane.showMessageDialog(null,processName).Below the file attached VM.zip.VM.zip Great workThanksNanaji Share this post Link to post Share on other sites
nooc9 0 Report post Posted September 17, 2009 For web applications there is a jnlp method of doing it. Check out javax.jnlp.SingleInstanceService found in jnlp.jar, included in the sdk. Share this post Link to post Share on other sites
iGuest 3 Report post Posted February 9, 2012 here is full working code for achieving single instance of application in java : How it works New instance of application tries to connect to a specific ServerSocket (localhost, port#) to detect running applications. And a running application must have a ServerThread to detect possible run of new instance of the same application The main Logic in steps Find existing server socket running on localhost If found(another instance was already running) --> exit current instance of application else -- start a new Server thread to detect run of future applications and start the application Share this post Link to post Share on other sites
iGuest 3 Report post Posted July 1, 2014 Hey Xico, First of all thanks for the code. I have implemented the same in my app. It's perfectly working for all windows os except windows 7. Can you please help me out in the same. Share this post Link to post Share on other sites
iGuest 3 Report post Posted July 7, 2014 I am facing issues on windows 7. This isn't working. However after installing netbeans it works. Also if I uninstall netbeans it still works. What's this mystery? Share this post Link to post Share on other sites