Bagaimana cara menghentikan proses Java dengan baik di Linux dan Windows?
Kapan Runtime.getRuntime().addShutdownHook
dipanggil, dan kapan tidak?
Bagaimana dengan finalisator, apakah mereka membantu di sini?
Dapatkah saya mengirim semacam sinyal ke proses Java dari shell?
Saya mencari solusi yang lebih disukai portabel.
Jawaban:
Hook shutdown dijalankan di semua kasus di mana VM tidak dibunuh secara paksa. Jadi, jika Anda mengeluarkan kill "standar" (
SIGTERM
dari perintah kill) maka mereka akan mengeksekusi. Demikian pula, mereka akan mengeksekusi setelah memanggilSystem.exit(int)
.Bagaimanapun hard kill (
kill -9
ataukill -SIGKILL
) maka mereka tidak akan mengeksekusi. Demikian pula (dan jelas) mereka tidak akan dijalankan jika Anda menarik daya dari komputer, menjatuhkannya ke dalam tong lava mendidih, atau memukul CPU menjadi beberapa bagian dengan palu godam. Anda mungkin sudah tahu itu.Finalizer benar-benar harus berjalan juga, tetapi yang terbaik adalah tidak bergantung pada itu untuk pembersihan shutdown, melainkan mengandalkan hook shutdown Anda untuk menghentikan semuanya dengan bersih. Dan, seperti biasa, berhati-hatilah dengan kebuntuan (saya telah melihat terlalu banyak kait penghentian yang menggantung seluruh proses)!
sumber
Ok, setelah semua kemungkinan yang saya pilih untuk bekerja dengan "Pemantauan dan Manajemen Java"
Ikhtisar ada di sini
Yang memungkinkan Anda untuk mengontrol satu aplikasi dari yang lain dengan cara yang relatif mudah. Anda dapat memanggil aplikasi pengontrol dari skrip untuk menghentikan aplikasi yang dikontrol dengan baik sebelum mematikannya.
Berikut kode yang disederhanakan:
Aplikasi yang dikontrol:
jalankan dengan parameter VM berikut:
-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"); } } }
Mengontrol aplikasi:
jalankan dengan berhenti atau mulai sebagai argumen baris perintah
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(); } } }
Itu dia. :-)
sumber
Cara lain: aplikasi Anda dapat membuka server socet dan menunggu informasi sampai padanya. Misal string dengan kata "ajaib" :) kemudian bereaksi membuat shutdown: System.exit (). Anda dapat mengirimkan informasi tersebut ke kaus kaki menggunakan aplikasi eksternal seperti telnet.
sumber
Berikut ini solusi yang agak rumit, tetapi portabel:
Saya menerapkan Agen Java. Ini tersedia di Github: https://github.com/everit-org/javaagent-shutdown
Penjelasan rinci tentang solusi tersedia di sini: https://everitorg.wordpress.com/2016/06/15/shutting-down-a-jvm-process/
sumber
Pertanyaan Serupa Disini
Finalisator di Java buruk. Mereka menambahkan banyak biaya tambahan untuk pengumpulan sampah. Hindari mereka jika memungkinkan.
ShutdownHook hanya akan dipanggil saat VM dimatikan. Saya pikir itu sangat baik mungkin melakukan apa yang Anda inginkan.
sumber
Pensinyalan di Linux dapat dilakukan dengan "kill" (man kill untuk sinyal yang tersedia), Anda memerlukan ID proses untuk melakukannya. (ps ax | grep java) atau semacamnya, atau simpan id proses saat proses dibuat (ini digunakan di sebagian besar file startup linux, lihat /etc/init.d)
Pensinyalan portabel dapat dilakukan dengan mengintegrasikan SocketServer dalam aplikasi java Anda. Tidak sesulit itu dan memberi Anda kebebasan untuk mengirim perintah apa pun yang Anda inginkan.
Jika yang Anda maksud akhirnya adalah klausul sebagai ganti finalizer; mereka tidak dieksekusi ketika System.exit () dipanggil. Finalizer seharusnya berfungsi, tetapi seharusnya tidak melakukan sesuatu yang lebih signifikan selain mencetak pernyataan debug. Mereka berbahaya.
sumber
Terima kasih atas jawaban Anda. Penutup kait penutup seperti sesuatu yang akan bekerja dalam kasus saya. Tetapi saya juga menemukan sesuatu yang disebut kacang Pemantauan dan Manajemen:
http://java.sun.com/j2se/1.5.0/docs/guide/management/overview.html
Itu memberikan beberapa kemungkinan bagus, untuk pemantauan jarak jauh, dan manipulasi dari proses java. (Diperkenalkan di Java 5)
sumber